Await关键字与等待类型一起使用(.NET附带现有的两种类型, Task和Task<T> )。 但是,可以编写自己的等待类型。
msdn博客文章指出:
你可以想到以下代码:
await FooAsync(); RestOfMethod();与此类似:
var t = FooAsync(); var currentContext = SynchronizationContext.Current; t.ContinueWith(delegate { if (currentContext == null) RestOfMethod(); else currentContext.Post(delegate { RestOfMethod(); }, null); }, TaskScheduler.Current);
上面的(伪)代码是否遵循awaitable类型的实现(例如Task ),或者它可能只是编译器处理await关键字右侧的任何等待类型的方式?
在下面的评论部分,有一篇文章解释了TaskScheduler和SynchronizationContext之间的区别。
主要区别在于SynchronizationContext是使用委托的一般机制,而TaskScheduler特定于并且适用于任务(您可以使用TaskScheduler.FromCurrentSynchronizationContext获取包装SynchronizationContext的TaskScheduler)。 这就是为什么等待任务考虑到两者,首先检查SynchronizationContext(作为大多数UI框架支持的更一般的机制),然后回退到TaskScheduler。 等待不同类型的对象可能会选择首先使用SynchronizationContext,然后再回退到特定于该特定类型的其他某种机制。
如果我正确理解了最后一句,这意味着我可以在continueWith方法中放置我想要的任何委托(我的意思是上面代码示例中的t.ContinueWith调用),即修改await在与我的自定义等待对象一起使用时的工作方式。
万一你想了解更多: http : //blogs.msdn.com/b/pfxteam/archive/2009/09/22/9898090.aspx
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
最满意答案
上面的(伪)代码是否遵循awaitable类型的实现(例如Task),或者它可能只是编译器处理await关键字右侧的任何等待类型的方式?
伪代码确实遵循任务的实现。 但它的存在只是为了帮助你理解它是如何工作的,因为它类似于延续。
编译器生成的实际代码差别很大, 并且不考虑实际的等待类型 。 它所做的就是寻找一个GetAwaiter方法,该方法返回一个具有IsCompleted , GetResult , OnCompleted的awaiter。 等待实现的是既可以捕获SynchronizationContext.Current也可以不捕获(或完全做其他事情)。
你可以在这里看到实际的代码。
即完全修改await与我的自定义等待对象一起使用时的工作方式。
只要对你有意义,你就可以做任何你喜欢的事。 您甚至可以使用扩展方法制作内置类型。 例如这段代码:
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); }将使您能够编译await "bar"; 。 它当然会在运行时失败,但编译器不知道这一点。
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.
更多推荐
发布评论