Quantcast
Channel: ICT Blog » Microsoft
Viewing all articles
Browse latest Browse all 39

Await anything

$
0
0

Did you know….

…that in C# 4.0 it’s possible to make anything awaitable by using extention methods. The only requirement for this is to implement a function called GetAwaiter(). Let say for example we want to await a certain timespan. All we have to do is create a function called GetAwaiter that extents the timespan type.

public static TaskAwaiter GetAwaiter(this TimeSpan timeSpan)
{
var tcs = new TaskCompletionSource();
Thread.Sleep(timeSpan);
tcs.SetResult(true);
return tcs.Task.GetAwaiter();
}

Once this is done, we can call the await within an async context.

private static async void RunAnythingAwaitable()
{
await TimeSpan.FromSeconds(10);
}

Nice ey? But what about custom objects that would require special handling when completed. No problem. We can also define custom TaskAwaiter for our custom object.

Lets say I have the following class:
public class CustomObject
{

public List SomeList { get; set; }
public bool Finished { get; set; }

public List Generate()
{
SomeList = new List();
for (var i = 0; i < 5000; i++)
{
SomeList.Add(string.Format("Item_{0}", i));
if (Math.Abs(Math.IEEERemainder(i, 100) - 0) <= 0)
{
Console.Write("{0}", i);
}
Thread.Sleep(5);
}
return SomeList;
}
}

It contains a simple function for this example that adds items to a string list. We can now define a custom await function for the execution of this task:

public struct CustomObjectAwaiter : INotifyCompletion
{
private readonly CustomObject _customObject;

public CustomObjectAwaiter(CustomObject customObject)
{
_customObject = customObject;
}

public void OnCompleted(Action continuation)
{
_customObject.Finished = true;
}

public List GetResult()
{
return _customObject.SomeList;
}
}

After we defined our custom TaskWaiter, we have to use this in our GetAwaiter extention method. Keep in mind, since our returntype in GetResult is of the type List, we’ll have to make this awaitable too.

public static CustomObjectAwaiter GetAwaiter(this CustomObject customObject)
{
return new CustomObjectAwaiter(customObject);
}

public static TaskAwaiter<List> GetAwaiter(this List results)
{
var tcs = new TaskCompletionSource<List>();
tcs.SetResult(results);
return tcs.Task.GetAwaiter();
}

Now we can call our await function with an async context for our custom object, and be sure that the result is of the type List.

private static void AwaitCustomObject()
{
ThreadPool.QueueUserWorkItem(async delegate
{
var customObject = new CustomObject();
await customObject.Generate();
Console.WriteLine("Generated {0} items",     customObject.GetAwaiter().GetResult().Count);
});
}

I agree one could wonder about the application of this particular await function, but this example shows you how it should be done. Hope this was usefull for you, and one day you might just have to await something.

Here (Techdays Tryouts) you can find a complete example with code in it.


Viewing all articles
Browse latest Browse all 39

Latest Images

Trending Articles





Latest Images