In WinRT any method that takes more than 50 ms is exposed as an asyncronous operation and thanks to C# await keyword (or Javascript’s Promises) what could be a programmer’s headache becomes a straightforward task, but what if you have your own asyncronous code?
Let’s say you have a basic downloader class that simulates downloading a string from the internet, in practice something like:

public class MyDownloader
{
public event EventHandler Completed;

public string Result { get; set; }

public void Download()
{
TimeSpan delay = TimeSpan.FromMilliseconds(1000);
var timer = ThreadPoolTimer.CreateTimer((tpt) =>
{
this.Result = DateTime.Now.Ticks.ToString();
this.Completed(this, EventArgs.Empty);
}
, delay);
}
}

this code simulates an asyncronous operation running on a secondary thread using WinRT’s ThreadPoolTimer that sets Result property to current ticks value and raises a Completed event.
To use it, the code required is:

private void Button_Click(object sender, RoutedEventArgs e)
{
MyDownloader downloader = new MyDownloader();
downloader.Completed += (s, a) =>
{
this.Dispatcher.Invoke(Windows.UI.Core.CoreDispatcherPriority.Normal, (t, o) => tb1.Text = downloader.Result,this,null);
};

downloader.Download();
}

We subscribe the event and when raised we use WinRT’s CoreDispatcher to mashal invocation back to UI thread (tb1 is a TextBlock element), no very ‘natural’ flow but that’s how we wrote code until now.
Let’s try to convert Download method to a WinRT’s  Async method adding a DownloadAsync method to MyDownloader class:
public Task<string> DownloadAsync()
{
TaskCompletionSource<string> taskCompletionSource = new TaskCompletionSource<string>();
this.Completed += (s, a) =>
{
taskCompletionSource.SetResult(this.Result); //SetException
};

this.Download();
return taskCompletionSource.Task;
}

Method is no longer void, but returns a Task<string> since we expect a string to be returned as operation result, we then invoke Download method as usual but when completed we ‘signal’ that operation has finished using SetResult (or SetException in case task failed and an exception need to be reported back to caller)
You might think: “Well’ not so easy either…”  but now let’s see the code required to get the same goal as before:

async private void Button_Click2(object sender, RoutedEventArgs e)
{
MyDownloader downloader = new MyDownloader();
tb1.Text= await downloader.DownloadAsync();
}

No more handlers, no more Dispatchers, just added async and await keywords and, more important, the code flow is absolutely linear even if execution continues to be asyncronous.
Lot easier isnt’ it?
 
Technorati Tags: ,,