Awaitable Managed Animation classes for WinRT (Part 3)

In the previous two posts, I set up the reasoning and infrastructure for creating a different type of animation infrastructure. In this post, I’ll (finally) show an actual example of how to use this infrastructure.

For this, we’ll create a simple application. Our first goal is to place numbered cards (1-5) on our canvas. The cards are represented by a simple UserControl named NumberCardControl which has a Text property specifying the content.

Our initialization code will dynamically create the cards and place them at the bottom of the screen. The final result will look like this:

image

And this is what the code looks like (it uses a couple of non-standard extension methods to simplify working with the Canvas control):

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
double width = canvas.ActualWidth;
double size = width / 20;
double top = canvas.ActualHeight / 4 * 3;
for (int i = 0; i < 5; i++)
{
NumberCardControl control = new NumberCardControl();
control.Text = i.ToString();
control.SetCanvasLocation(new Point(width / 5 * i + width / 5 / 2, top));
control.Width = control.Height = size;

// When we do the animation, we will uncomment this code.

// control.Opacity = 0;
canvas.Children.Add(control);

}
}

Animation anyone?

Right now, the code simply places the cards on the canvas. There’s no entrance animation or anything happening. It’s very abrupt. What if we want to animate these controls in? Say, by changing their opacity from 0 to  1 gradually?

That’s where our infrastructure (finally) enters… First, we’ll need a derived class that knows how to animate opacity:

public class OpacityManagedAnimation : ManagedAnimation
{
public double Opacity{ get; set; }
public TimeSpan Duration { get; set; }
public EasingFunctionBase EasingFunction { get; set; }

public OpacityManagedAnimation(double opacity, TimeSpan duration, EasingFunctionBase easingFunction = null)
{
Opacity = opacity;
Duration = duration;
EasingFunction = easingFunction;
}

There are three properties we will use:

  1. Opacity: This is the target opacity we want the element to arrive at.
  2. Duration: This is the total duration of the animation.
  3. EasingFunctionBase: This is the easing function we want the opacity to animate with.

Finally, we have a constructor that sets all of these (and has a default for the easing function).

Next, we need to implement the two virtual functions:

public override void Retain()
{
Element.Opacity = ForceFinalValueRetained ? Opacity : Element.Opacity;
}

protected override Windows.UI.Xaml.Media.Animation.Storyboard CreateStoryboard()
{
Storyboard board = new Storyboard();
var timeline = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(timeline, Element);
Storyboard.SetTargetProperty(timeline, "Opacity");
var frame = new EasingDoubleKeyFrame() { KeyTime = Duration, Value = Opacity, EasingFunction = EasingFunction};
timeline.KeyFrames.Add(frame);
board.Children.Add(timeline);

return board;
}

As you can see, Retain is pretty straight-forward. It either takes the target Opacity value or the current Opacity (depending on ForceFinalValueReturned that I discussed in the previous post) and sets it into the property so that when we stop the Storyboard, the element will have the Opacity we actually want.

Next, we need to create the Storyboard. This is fairly simple boilerplate code for anyone who coded Storyboards before, so just to summarize what it does:

  1. Create an instance of a Storyboard and Timeline classes.
  2. Tell the timeline what object and property it’s going to animate.
  3. Create a frame that will specify the animation to cause (with the Value property set to the target opacity).
  4. Add the frame to the timeline and the timeline to the storyboard.
  5. return the storyboard.

That’s it! We now have our first animation class and we can start using it!

Simple animation

First, let’s do some simple animation with the cards. We’ll make them all appear on the canvas at the same time, within 1 second of the page appearing.

The code is fairly simple:

TimeSpan duration = TimeSpan.FromSeconds(1);
foreach (var item in canvas.Children.OfType<FrameworkElement>())
{
new OpacityManagedAnimation(1, duration).Activate(item);
}

We new up an OpacityManagedAnimation class and immediately call the .Activate() method on it.

This is an awaitable operation (Activate() returns a Task) but in this instance we are not even awaiting it because we don’t really need to do anything with it.

Running the app, you will see the the elements appearing together!

Staggering the animation

The animation is pretty boring right now. The cards appear at the same time. What if we wanted to stagger the animation so that they appear one after the other?

private async Task StaggeredAnimationAsync()
{
TimeSpan duration = TimeSpan.FromSeconds(1);
List<Task> tasks = new List<Task>();
foreach (var item in canvas.Children.OfType<FrameworkElement>())
{
tasks.Add(new OpacityManagedAnimation(1, duration).Activate(item));
await Task.Delay(300);
}

await Task.WhenAll(tasks.ToArray());
}

Here’s what we are doing:

  1. We go over the controls, activating the opacity animation just like we did before.
  2. However, we also await a call to Delay()  which will essentially add a short pause before each activation.
  3. We also collect the animation tasks we added into a list.
  4. At the end, we await all the animation tasks so that the overall Task will be done only once all the animations are done.

Flickering the elements

To make our example even more complicated, let’s say we want to flicker the elements – go up to 0.6 opacity, then back to 0.2, then to 0.7, then to 0.3 until we reach an opacity of 1  (+0.1 for the target, and go down by 0.4 until we hit 1 as the opacity).

Again – this is a very easy piece of code to run. First, we’ll write up the piece of code that will calculate the opacities:

private async Task FlickerAndAppearAnimationAsync()
{
for (double max = 6; max <= 10; max += 1)
{
await FlickerToValueAsync(max / 10, max / 10 - 0.4);
}
}

The code simply loops and makes the calculations I described above – it then calls FlickerToValueAsync()which takes the top value, and the value we want to back down to each time (until we reach full opacity).

 

private async Task FlickerToValueAsync(double to, double backDownTo)
{
TimeSpan duration = TimeSpan.FromSeconds(0.5);
List<Task> tasks = new List<Task>();
foreach (var item in canvas.Children.OfType<FrameworkElement>())
{
tasks.Add(new OpacityManagedAnimation(to, duration).Activate(item));
}

await Task.WhenAll(tasks.ToArray());
await Task.Delay(100);

if (to < 1)
{
tasks.Clear();
foreach (var item in canvas.Children.OfType<FrameworkElement>())
{
tasks.Add(new OpacityManagedAnimation(backDownTo, duration).Activate(item));
}

await Task.WhenAll(tasks.ToArray());
}
}

The code has two loops in it. The first brings the various elements in the canvas to the “to” opacity (1st argument) and the second loop (which only runs if the target opacity is still less than 1) brings the opacity back down to the backDownTo argument.

In the middle, we add a short delay and that’s it. Voila.

Is this really easier than traditional Storyboards?

The short answer is that it is and it isn’t.

Using this method is more complicated than had you defined your Storyboard in a rigid manner in Blend, for example. However.. What if your list of 5 controls was not rigid? In the code I presented, if you want 10 controls, you simply touch that number in the initialization function and voila! Everything keeps working – no need to adjust any Blend designer or anything. No need to copy animations over in XAML. It’s all written in code and is fully dynamic. The staggered animation, for example, will always be perfectly staggered without having to manually set the timelines in XAML or Blend.

In the next post, I’ll discuss some more ManagedAnimation derivatives you can use to animate elements in your XAML application in a similar manner.

Posted in Animation, Dev, Windows8 | Leave a comment

Awaitable ManagedAnimation class for WinRT (Part 2)

In the first part of this post series, I discussed the reasoning behind potentially wanting to have a second way of doing animation in XAML.

In this post, I will discuss the basic infrastructure for this new way of doing thing animation.

The Orchestration class

In the root of the infrastructure reside two classes – the ManagedAnimation and Orchestration classes. Orchestration is a static helper class with some utilities pertaining mostly to how storage of the currently running animations. For each element that’s participating in this new system, it will store a list of currently active ManagedAnimation instances by way of an attached dependency property:

public class Orchestration
{
public static readonly DependencyProperty ManagedAnimationsProperty =
DependencyProperty.RegisterAttached("ManagedAnimations", typeof(List<ManagedAnimation>), typeof(Orchestration), new PropertyMetadata(null));


public static List<ManagedAnimation> GetManagedAnimations(DependencyObject obj)
{
return (List<ManagedAnimation>)obj.GetValue(ManagedAnimationsProperty);
}

public static void SetManagedAnimations(DependencyObject obj, List<ManagedAnimation> value)
{
obj.SetValue(ManagedAnimationsProperty, value);
}

 

That’s pretty simple. On top of that, we’ll add a couple of helper methods that will make working with this class easier:

First off, the VerifyList method which makes sure there’s a list of ManagedAnimation instances available on a given element:

private static List<ManagedAnimation> VerifyList(ManagedAnimation managedAnimation)
{
var list = GetManagedAnimations(managedAnimation.Element);
if (list == null)
{
SetManagedAnimations(managedAnimation.Element, list = new List<ManagedAnimation>());
}
return list;
}

The relevant DependencyObject is extracted from ManagedAnimation (we’ll see this a bit later) and the method makes sure there’s a list instantiated and available.

Next, we have two methods – one for adding and one for removing a ManagedAnimation to a DepenedencyObject (usually to a FrameworkElement):

internal static void AddManagedAnimation(ManagedAnimation managedAnimation)
{
var list = VerifyList(managedAnimation);
int index = list.IndexOfItem(x => x.Equivalent(managedAnimation));
if (index != -1)
{
var managed = list[index];
managed.Retain();
managed.Stop();
list.RemoveAt(index);
}

list.Add(managedAnimation);
}

internal static void RemoveManagedAnimation(ManagedAnimation managedAnimation)
{
var list = GetManagedAnimations(managedAnimation.Element);
if (list != null)
{
managedAnimation.Retain();
managedAnimation.Stop();
list.Remove(managedAnimation);
}
}

The functionality is fairly straightforward. The only interesting bit here is that before adding a ManagedAnimation instance from the list, the call makes sure an equivalent one is not already applied (for more information about Equivalent(), see below). The call also makes sure to call Retain() and Stop() to keep the values that are currently assigned and stop the currently running animation. If the animation was not stopped, the new Storyboard, when called to start, would throw (since you cannot animate the same property of the same object more than by one Storyboard at any given time).

That’s it. We now have a simple utility class that can keep track of the various animations currently running on a given element.

The ManagedAnimation class

This is where things start to get a little more interesting. The ManagedAnimation class is a base class used to apply animation to a given element. It contains the basic management routines and takes care of [most] of the legwork needed.

public abstract class ManagedAnimation
{
private Storyboard m_storyboard;
private ManagedAnimationCompleteEventArgs m_completeResult = new ManagedAnimationCompleteEventArgs() { NaturallyCompleted = true };

public bool ForceFinalValueRetained { get; set; }
public FrameworkElement Element { get; protected set; }
// ...
}

The class contains a handful of fields/properties:

  • m_storyboard: This class contains the animation definition applied by this ManagedAnimation instance. As you will see in a bit, the derived classes are the ones that are going to “fill” it up.
  • m_completeResult: This is the value returned when awaiting an animation. It contains some simple information such as whether or not the animation was completed naturally.
  • ForceFinalValueRetained: This property specifies whether the animation will “snap” to the final value specified when stopped before it’s complete, or if it’s going to stay where it is. For animation to look “continuous”, this will almost always be false. An example for when this should be true is if there’s an especially long running animation of Opacity and a second animation of Opacity may start at some point before the end. When that’s the case, the developer may pass true for this value, and the infrastructure will make sure Opacity goes to it’s final animation value before starting to animate again.
  • FrameworkElement: This is the element the animation will operate on.

Next comes the important bit of this class – the actual activation of the animation:

public async Task<ManagedAnimationCompleteEventArgs> Activate(FrameworkElement element, bool forceFinalValueRetained)
{
if (Element != null)
{
throw new InvalidOperationException();
}
ForceFinalValueRetained = forceFinalValueRetained;
Element = element;
m_storyboard = CreateStoryboard();
Orchestration.AddManagedAnimation(this);
await m_storyboard.BeginAsync();

m_storyboard = null;
Orchestration.RemoveManagedAnimation(this);
Element = null;

var result = m_completeResult;

return result;
}

The activation method sets the various parameters it gets on the class and then proceeds to start the animation. First, it creates the Storyboard by calling the abstract CreateStoryboard() method which will be implemented by the derived classes. It then calls the BeginAsync() extension method on the created Storyboard (more about that one at the end of this post) and awaits it.

This makes the animation sequence start.  When the animation is complete, the activate method cleans up after itself – it calls the Orchestration class to remove itself from the element, nullifies a bunch of fields/properties and returns.

protected abstract Storyboard CreateStoryboard();

public virtual bool Equivalent(ManagedAnimation managedAnimation)
{
return managedAnimation.GetType() == GetType();
}

public abstract void Retain();

The final three interesting methods in the class are:

  1.  CreateStoryboard() we touched on before – inheriting classes do the heavy-lifting there and build the relevant Storyboard.
  2. Equivalent() is used by the Orchestration class to figure out if one ManagedAnimation class is equivalent to another and as such needs to cancel an existing one.
  3. Retain()  is used at the end of an animation to “nail” the current state of the object so that it will remain there (since we are stopping the animation).

A note about Storyboard.BeginAsync()

BeginAsync() is an extension method available in the Extensions class in the library. It uses a fairly standard mechanism for transforming an event into an awaitable operation (an operation returning a Task instance).

public static Task BeginAsync(this Storyboard storyboard)
{
return EventToTaskAsync<object>(
e => { storyboard.Completed += e; storyboard.Begin(); },
e => storyboard.Completed -= e);
}

The code for EventToTaskAsync() is also available in the download (which will be available at the final post).

What’s next?

The next post in this series will discuss how to implement the OpacityManagedAnimation class – used to change opacity of objects. The post will also contain the first simple application that will make use of this animation.

Posted in Animation, Dev, Windows8 | Leave a comment

Different approach for animation in XAML using .NET 4.5 new async functionality (Part 1)

This post discusses a small set of classes we use to do dynamic animation in XAML apps – animation where the developer, at design time, might not know a lot about what needs to be animated and when. I’ve been using this “infrastructure” for a few months now and it seems to fill it’s niche pretty well…

First, a little background…

The various XAML infrastructures (WPF, Silverlight, Windows Store apps) have built in support for animation through Storyboards. Storyboards are non-visual elements that orchestrate an animation sequence involving one or more visual (and sometimes non visual) elements on the screen. The animation is executed primarily through the DependencyObject infrastructure that XAML brings to the table (which, incidentally, means animations do not need to be visual  – they can just affect internal object states that are not usually considered animation).

For the purpose of this post, you don’t really need to understand storyboarding in XAML, but it would help you understand what’s happening under the covers.

Storyboard advantages and disadvantages

For pre-canned animation that does not vary and that needs to be carefully orchestrated, Storyboards shine. Especially when paired with good tools like Blend (once you figure out how it works), Storyboards are great. They let you create very pleasing effects, transitions and animations with a minimum amount of work. Furthermore, Storyboards that are expressed in XAML are declarative, and as such can easily be parsed “understood” and modified by external tools (like Blend).

Where Storyboard fall short, in my opinion, is when the developer has a set of elements they want to animate, but information such as the number of elements, their position, their size etc is not necessarily known in advance. Similarly – if the stages of the animation can change arbitrarily, Storyboards don’t really play well with that.

The reasons behind these issues all stem from the fact that you cannot modify a Storyboard while it’s “in flight” – once a Storyboard starts up, any changes (other than pausing and restarting) cannot be made. Furthermore, when a Storyboard stops, all the elements it animated “snap back” to their original position before the animation. Often, you will run a Storyboard indefinitely, essentially “pinning” the end-of-animation values it has for all the elements it affects. Another subtle issue is that even if you wrote extensions for Storyboards that will let you stop one in it’s tracks, modify it, and continue from that same spot (not trivial by any stretch of the imagination), the animations will seem to “jerk” as Easing functions applied to the animations will be recalculated from scratch, causing the animations to seem off.

Writing your own animation engine

The issues Storyboards have can be fixed by manually animating objects. Writing your own code, with loops and timing etc that will allow you to modify values of properties on UI elements, making them animate. There are two big issues with this:

1. It’s a lot of work – creating an animation engine that compensates for rendering lag, for difference between performance and for periods of heavy animation is a non-trivial task. Worse – it’s already been done by Microsoft – it’s called a Storyboard!

2. It’s not going to be as efficient – the XAML infrastructure can make a lot of assumptions (and has more internal knowledge) than you ever will on what’s going on inside it. What this means is that a ton of the code that actually does the animation will actually run on a thread different than the UI thread – a privilege we as 3rd party developers don’t have.

Goals for our solution

The solution provided here has 2 main goals:

1. Make use of the existing XAML animation infrastructure to animate UI elements.

2. Make it so that these animations can be easily orchestrated in code and have them be individually modifiable so that any animation can be changed “in flight”.

So.. What’s your solution?

The next 2-3 posts are going to show the solution I came up with to work around the limitations of doing truly dynamic animation. I will then show a (very) simple app that will make use of said animation infrastructure.

The dynamic (or “Managed”) animation system is fairly simple and is based on the following concepts:

  1. Granularity: Each managed animation consists of a single Storyboard and usually one or two timelines inside said Storyboard. That’s different from how you usually do animation in XAML which is by having a single Storyboard handling multiple time lines.
  2. Element-centric: Said storyboards are attached to a given FrameworkElement. If you want to move an image on your canvas from point A to point B, you will apply a single managed animation to it that will do that (a Storyboard, with 2 timelines, one animating Canvas.Top and one animating Canvas.Left). If you also want to animate the opacity of the element, you will also apply a second managed animation (orthogonally) which will handle that.
  3. Self managing: Animations are asynchronous in nature. The developer may decide to abruptly apply a different animation to the same element in essence interrupting the previous one. In these cases, the developer need not handle the cancellation (usually) – they just apply the new animation and the previous one will stop applying.
  4. Composition/orchestration through code: Orchastration of animation will happen through code and through the new facilities built into .NET 4.5 – if the developer wants to wait for two separate managed animations to complete, they can simply await both animations.

That’s it! The next post will discuss the basic building block – the ManagedAnimation class, how it works and what it does.

Post 2

Post 3

Post 4

Posted in Animation, Dev, Windows8 | Leave a comment

DEP0500 and DEP1000 errors when deploying Windows Store apps from VS

One of my biggest problems is that I have a horrendous memory. For everything. From forgetting my coat to remembering to pay my credit card on time. Just terrible. For programming-related issues, my memory is not so terrible, but still pretty darn bad.

A few days ago, I started having issues when deploying files from VS on my Windows 8 machine (same machine, running in Simulator or Local). Every 3 or 4 executions/runs, Visual Studio will tell me that it could not deploy the file because it was in use (or because it’s directory was in use – sometimes one, other times the other).

I did all the usual things. Restarted VS, rebooted the computer etc. Nothing really helped – every few executions I was forced to restart VS. Using Process Explorer showed me that yes, indeed, VS was keeping a hold on the handle.

Madness.

The thing that drove me up the wall was that I vaguely remembered running into a similar issue a few months back and for the life of me could not remember what I did to fix it.

Then… Late at night.. Some random neuron fired. Which allowed 2 other neurons to fire. Which caused a cascade of neurons to transmit electricity slowly through my brain, which allowed my faulty memory to surface what I did last time..

TL;DR

Next time this happens to you, simply tell VS to reset all it’s settings. Tools\Import Export Settings/Reset Settings.

That’s it. Did that, restarted VS and the problem went bye bye.

Bliss.

Posted in Dev, VisualStudio, Windows8 | Tagged , , , , | Leave a comment

Maintain ScrollViewer scroll position across page navigation/app reactivation

When navigating around your app, it could be really helpful to maintain scroll position on various ScrollViewer controls. This also applies when your app reactivates after being suspended and shut down.

Doing it is a bit trickier than it looks since the two scroll  position properties on a ScrollViewer are read-only (you need to use a method to navigate around). I can up with the following code to take care of this. Note that this could be done better by hooking directly to the LayoutAwarePage.  (Note that the code as presented relies on you inheriting from LayoutAwarePage, but you could implement the same thing with any other data binding mechanism you employ.

How it works

  1. You maintain the scroll position in DefaultDataView. When SaveState() is called, you take the value from DefaultDataView and place it in state.
  2. Similarly, when LoadState() is called, you copy the value into DefaultDataView (or zero if there is no such value).
  3. You use the supplied dependency properties (below) to bind the ScrollViewer.
  4. Profit!

SaveState/LoadState

Here’s what the code looks like when saving state – note how we simply take the ScrollerPosoition key from the DefaultViewModel and copy it to the page state.

protected override void SaveState(Dictionary<string, object> pageState)
{
base.SaveState(pageState);
pageState["ScrollerPosition"] = DefaultViewModel["ScrollerPosition"];
}

Load is similar, but in the other direction:

protected override void LoadState(Object navigationParameter,

Dictionary<String, Object> pageState)
{
base.LoadState(navigationParameter, pageState);
DefaultViewModel["ScrollerPosition"] =

GetPageStateOrDefault("ScrollerPosition", pageState, 0.0);
}

Here’s the implementation for GetPageStateOrDefault() added to LayoutAwarePage:

protected T GetPageStateOrDefault<T>(string key, Dictionary<string, object> pageState, T def)
{
T result = def;
if (pageState != null)
{
result = pageState.GetValueOrDefaultTyped(key, result);
}

return result;
}

 

Attached property + binding

You define the following attached property in your code (it’s a self contained class):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NotSystem.Windows.Interactivity;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace SocialEbola.Lib.Behaviors
{
public class ScrollPositionBehavior : DependencyObject
{
public static readonly DependencyProperty HorizontalScrollOffsetForStateProperty =
DependencyProperty.RegisterAttached("HorizontalScrollOffsetForState", typeof(double), typeof(ScrollPositionBehavior), new PropertyMetadata(Double.NaN, DependencyPropertyChanged));
public static readonly DependencyProperty HookedProperty =
DependencyProperty.RegisterAttached("Hooked", typeof(bool), typeof(ScrollPositionBehavior), new PropertyMetadata(false));

private static bool GetHooked(FrameworkElement obj)
{
return (bool)obj.GetValue(HookedProperty);
}

private static void SetHooked(FrameworkElement obj, bool value)
{
obj.SetValue(HookedProperty, value);
}

public static double GetHorizontalScrollOffsetForState(FrameworkElement obj)
{
return (double)obj.GetValue(HorizontalScrollOffsetForStateProperty);
}

public static void SetHorizontalScrollOffsetForState(FrameworkElement obj, double value)
{
obj.SetValue(HorizontalScrollOffsetForStateProperty, value);
}

private static void DependencyPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
if (args.Property == HorizontalScrollOffsetForStateProperty)
{
HookIfNeeded((FrameworkElement)obj);
}
}

private static void HookIfNeeded(FrameworkElement element)
{
if (!GetHooked(element))
{
element.Loaded += Obj_Loaded;
element.Unloaded += Obj_Unloaded;
var viewer = GetScrollViewer(element);
if (viewer != null)
{
viewer.ViewChanged += Viewer_ViewChanged;
}
SetHooked(element, true);
}
}

static void Viewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
if (!e.IsIntermediate)
{
var viewer = GetScrollViewer(sender);
if (viewer != null)
{
SetHorizontalScrollOffsetForState((FrameworkElement)sender, viewer.HorizontalOffset);
}
}
}

static void Obj_Unloaded(object sender, RoutedEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
element.Loaded -= Obj_Loaded;
element.Unloaded -= Obj_Unloaded;
var viewer = GetScrollViewer(element);
if (viewer != null)
{
viewer.ViewChanged -= Viewer_ViewChanged;
}

SetHooked(element, false);
}

private static ScrollViewer GetScrollViewer(object element)
{
return element as ScrollViewer;
}

static void Obj_Loaded(object sender, RoutedEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
var viewer = element as ScrollViewer;
if (viewer != null)
{
viewer.ScrollToHorizontalOffset(GetHorizontalScrollOffsetForState(element));
}
}
}
}

 

Finaly, in XAML, you bind this property to your DefaultViewModel:

 

<ScrollViewer x:Name="scroller" 
Grid.RowSpan="2"
Padding="0,137,0,0"
Style="{StaticResource scrollerStyleLandscape}"
sebehaviors:ScrollPositionBehavior.HorizontalScrollOffsetForState="{Binding ScrollerPosition, Mode=TwoWay}">

Once all of this is done you are good – any navigation back into your page will cause the system to restore it’s position.

Posted in Dev, Windows8 | Tagged , , , , , , , | Leave a comment

But in DataContractSerializer–does not handle object-types well

In using SuspensionManager and the Session State on Windows 8, I tried saving an object into it and the app kept crashing on load.. Just spent four hours chasing my tail…

Finally figured it out. Here it is if anyone else is hitting it.

If you have a class pointing to object and that object is actually a class where the Namespace property on the DataContractAttribute is empty, you are going to fail deserialization.

The solution is simple (usually) – give that class a namespace..

Repro

Given class MyClass:

//[DataContract(Namespace = "http://dotnetfail")]
[DataContract(Namespace = "")]
public class MyData
{
}

The following code will throw on the last line. Notice how serialization works fine as long as you don’t actually point to MyClass from an object type (the first part)

// This will work
DataContractSerializer ser = new DataContractSerializer(typeof(MyData));
MemoryStream stream = new MemoryStream();
ser.WriteObject(stream, new MyData());
stream.Position = 0;
ser.ReadObject(stream);

// This will throw (at the end)
ser = new DataContractSerializer(typeof(Dictionary<string, object>), new Type[] { typeof(MyData) });
stream = new MemoryStream();
var dict = new Dictionary<string, object>();
dict["MyObject"] = new MyData();
ser.WriteObject(stream, dict);
stream.Position = 0;
ser.ReadObject(stream);

The error points to a bogus location in the XML and gives a bogus exception description, sadly (which is why it took me so long to find it).

The following exception is thrown:

Error in line 1 position 202. 'EndElement' 'KeyValueOfstringanyType' from 
namespace 'http://schemas.microsoft.com/2003/10/Serialization/Arrays' is not
expected. Expecting element 'Value'.
 
Hope this saves some time for someone.
Posted in Dev, Windows8 | Tagged , , , , , | Leave a comment

ColdTask implementation for Windows 8

Tasks in Windows 8 are used all over the place – they are a really great way of getting things done asynchronously. Sometimes though, you find yourself wanting to change the way these tasks execute.

Most .NET tasks are “hot” – meaning they run when they are created or as soon as they can run. The two exceptions I could find were new Task(Action) and TaskCompletionSource. image

Most tasks people use in Windows 8 are consumed via the await keyword, applied to a method or task. These are hot as well.

What if you wanted to create a task where you controlled the start of which? This capability is not usually required – so far I have only encountered the need when doing locking. The problems you may run into when mixing locks and tasks are:

  1. You cannot await a task from within a lock (nor should you be able to).
  2. If you call the task from within the lock (so you can await it outside of the lock), the code will start running – if that code does something that should not happen inside the lock, you are in a bind.

There are a number of suggestions for solutions that I saw, but I have not seen an end to end class that does it, so here goes..

ColdTask and ColdTask<T> classes

These two classes let you create a cold task from an existing task. As an example, say you have a task you want running at most once in your system at any given time. Here’s a simple example of how to create the cold task:

ColdTask<string> coldTask = null;
coldTask = new ColdTask<string>(() => RunAsync());
// Can call coldTask.GetTask() to get the task here, if needed.

The important bit here is that ColdTask() takes a delegate that creates the task, so that it can defer this to when the caller would want to use it – in this case, it simply calls an async function called RunAsync().

That’s the preparation part – at a later time, you want to start and await the task:

await coldTask.Start();

That’s it – that’s all it takes.

How does it work?

The class itself is pretty simple. First off, fields and constructor:

public class ColdTask<TResult>
{
private Func<Task<TResult>> m_factory;
private Task m_bootstrapper;
private Task<TResult> m_task;



public ColdTask(Func<Task<TResult>> factory)
{
m_factory = factory;
m_bootstrapper = new Task(() => { });
}

m_bootstrapper is the task that will “halt” the execution so that it can later be “resumed”. In essense, we are using that empty Action delegate as a suspend mechanism.

Next, we have the implementation of GetTask() which returns the suspended task:

public Task<TResult> GetTask()
{
if (m_task == null)
{
m_task = InternalGetTask();
}

return m_task;
}

private async Task<TResult> InternalGetTask()
{
await m_bootstrapper;
return await m_factory();
}

InternalGetTask() awaits the bootstrapper and then calls the delegate passed in the constructor and awaits that. Since the bootstrapper is not started yet, you can see how it acts like a “suspend” mechanism.

GetTask() caches the task so that it won’t get created twice if it’s called.

Finally, Start does just that – starts the suspended empty task:

public Task<TResult> Start()
{
m_bootstrapper.Start();
return GetTask();
}

And that’s it pretty much!

You can download the cs file containing this class (as well as a non-generic version), you can download it here.

Posted in Dev, Windows8 | Tagged , , , , , , | Leave a comment