实现是否会改变等待的行为?

Await关键字与等待类型一起使用(.NET附带现有的两种类型, TaskTask )。 但是,可以编写自己的等待类型。

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

上面的(伪)代码是否遵循awaitable类型的实现(例如Task),或者它可能只是编译器处理await关键字右侧的任何等待类型的方式?

代码确实遵循任务的实现。 但它的存在只是为了帮助你理解它是如何工作的,因为它类似于延续。

编译器生成的实际代码差别很大, 并且不考虑实际的等待类型 。 它所做的就是寻找一个GetAwaiter方法,该方法返回一个具有IsCompletedGetResultOnCompleted的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"; 。 它当然会在运行时失败,但编译器不知道这一点。