Reputation: 572
Await
keyword is used with awaitable types (.NET comes with existing two such types, Task
and Task<T>
). However, it's possible to write your own awaitable type.
The msdn blog post states that:
you can think of the following code:
await FooAsync(); RestOfMethod();
as being similar in nature to this:
var t = FooAsync(); var currentContext = SynchronizationContext.Current; t.ContinueWith(delegate { if (currentContext == null) RestOfMethod(); else currentContext.Post(delegate { RestOfMethod(); }, null); }, TaskScheduler.Current);
Does the (pseudo)code above follow from the implementation of awaitable type (such as Task
), or maybe is it just the way the compiler deals with any awaitable type that is on the right of the await
keyword?
In the comments section below, there's a post explaining the difference between TaskScheduler and SynchronizationContext.
The primary difference is that SynchronizationContext is a general mechanism for working with delegates, whereas TaskScheduler is specific to and catered to Tasks (you can get a TaskScheduler that wraps a SynchronizationContext using TaskScheduler.FromCurrentSynchronizationContext). This is why awaiting Tasks takes both into account, first checking a SynchronizationContext (as the more general mechanism that most UI frameworks support), and then falling back to a TaskScheduler. Awaiting a different kind of object might choose to first use a SynchronizationContext, and then fall back to some other mechanism specific to that particular type.
If I understand the last sentence correctly, it means I can put any delegate I want in the continueWith
method (I mean the t.ContinueWith
call in code sample above), i.e. modify how await
works when used with my custom awaitable object.
Just in case you want to know more: http://blogs.msdn.com/b/pfxteam/archive/2009/09/22/9898090.aspx
Upvotes: 1
Views: 133
Reputation: 116548
Does the (pseudo)code above follow from the implementation of awaitable type (such as Task), or maybe is it just the way the compiler deals with any awaitable type that is on the right of the await keyword?
The pseudo code does follow from the implementation of tasks specifically. But it exists only to help you understand how it works because it's similar to continuations.
The actual code the compiler generates is widely different and it doesn't take the actual awaitable type into consideration. All it does is look for a GetAwaiter
method that returns an awaiter that has IsCompleted
, GetResult
, OnCompleted
. The awaitable implementation is the one that either captures SynchronizationContext.Current
or not (or does something else entirely).
You can see the actual code here.
i.e. completely modify how await works when used with my custom awaitable object.
You can do whatever you like as long as it makes sense to you. You can even make built-in types awaitable with an extension method. For example this code:
public static Awaiter GetAwaiter(this string s)
{
throw new NotImplementedException();
}
public abstract class Awaiter : INotifyCompletion
{
public abstract bool IsCompleted { get; }
public abstract void GetResult();
public abstract void OnCompleted(Action continuation);
}
Will enable you to compile await "bar";
. It will fail on runtime of course, but the compiler doesn't know that.
Upvotes: 4