2011-10-12 60 views
8

我还没有机会看看C#的异步/等待新功能的CTP,但我想知道的是:C#5中的新异步/等待功能如何与消息循环集成?

它如何与消息循环集成?我假设在一个标准的Windows应用程序(Winforms,WPF)中,通过使用Dispatcher或类似的函数向应用程序的消息循环发送消息来调用continuations?

如果我不使用标准的Windows消息循环会怎么样?例如,在GTK#应用程序或控制台应用程序中(如果在控制台应用程序中确实可以使用该功能)。

我已经在互联网上搜索有关此信息,但无济于事。谁能解释一下?

回答

5

它使用System.Threading.SynchronizationContext.Current。 WPF和Winforms都安装了自己的SynchronizationContext版本。它们使用它们的消息循环将来自工作线程的调用封送回主UI线程。分别使用Dispatcher.Begin/Invoke和Control.Begin/Invoke()。

在控制台模式应用程序中完成这项工作并不容易,它的主线程没有一个定义良好的'空闲'状态,允许以安全的方式注入封送的方法调用,以避免再次出现头痛问题。你当然可以添加它,但你会重新发明消息循环。

+0

谢谢Hank。尝试考虑在控制台应用程序中使用异步并失败的情况。所以我认为在这种情况下缺乏同步环境大多是没有意义的。 – Grokys

+3

[AsyncEx](http://nitoasyncex.codeplex.com/)包含一个[AsyncContext](http://nitoasyncex.codeplex.com/wikipage?title=AsyncContext)类,它为控制台应用程序提供异步兼容的主循环(和单元测试)。 –

+0

更多关于'SynchronizationContext' [这里](http://msdn.microsoft.com/en-us/magazine/gg598924.aspx)。 –

4

这一切都归结为“awaiter”在继续传递时所做的事情。

BCL中Task<T>的实现将使用当前的同步上下文(unless you ask it not to using ConfigureAwait) - 这意味着在WPF/SilverLight中它将使用调度程序;在Windows窗体中,它将使用类似Control.BeginInvoke的东西,并且在线程池线程中它只会在任何线程池线程上运行。请注意,这是您当前的上下文在等待表达这一点很重要,因为这是任务将捕获的延续运行。

链接的博客文章(由Mads Torgersen撰写)很好地解释了它如何在隐藏条件下工作,并且我有一个series of blog posts,您可能也会发现它。

+0

谢谢乔恩。在我所有的.Net域游览中,我从来没有遇到SynchronizationContext.Current,这是我认为你的意思是“当前同步上下文”?每天学些新东西。 – Grokys

+1

@格洛斯基:是的。 Stephen Toub的关于异步性能的文章还有更多:http://msdn.microsoft.com/en-us/magazine/hh456402.aspx –