我正在使用异步CTP进行一些探测,但是我没有得到好结果,因为GUI被阻止了。
我有一个带有按钮的WPF应用程序和一个用于日志的textBox。然后我有这个代码:
private async void btnAsync01_Click(object sender, RoutedEventArgs e)
{
UpdateTxtLog("Enter in Button Async01: " + System.DateTime.Now);
await metodo01Async();
UpdateTxtLog("Exit button Async01: " + System.DateTime.Now);
}
private async Task slowMethodAsync()
{
UpdateTxtLog("Enter in slowMethod: " + System.DateTime.Now);
Thread.Sleep(5000);
UpdateTxtLog("Exit slowMethod: " + System.DateTime.Now);
}
如果没有错误,设置一个方法用“sync”(在这种情况下点击事件),它让方法使用await,将执行点返回到调用实际方法的方法,然后执行返回到GUI。
所以在GUI中,我单击按钮,然后在click事件中等待slowMethod,我如何使用await与slowMethod控件应该返回到GUI,然后不应该阻止GUI。但是,在slowMethod完成之前,GUI被阻止并且txtLog不显示任何信息。
这是因为slowMethod是在与GUI相同的线程中执行的吗?如果我错了,async通常使用与调用await方法的方法相同的线程,但我认为async的原因是避免这种情况。
如何在没有thread.Sleep的情况下模拟slowMethod?也许这就是问题,因为在slowMethod我睡眠线程,而slowMethod的线程与GUI相同。
这让我觉得总是建议在其他线程中执行异步方法的代码?如果这是正确的,这是使用异步的意义,如果我还需要使用任务不阻塞主线程?
何时使用异步以及何时使用任务?
对于此探针,我正在关注此网站中的示例:http://www.codeproject.com/Articles/127291/C-5-0-vNext-New-Asynchronous-Pattern
在这个例子中,它使用client.DownloadStringTaskAsync作为slowMethod,但在我的情况下,我使用虚拟方法而不是使用WebClient,使用sleep来模拟slowMethod。我认为这是独特的差异。
感谢。 Daimroc。
答案 0 :(得分:2)
使用await TaskEx.Delay(5000)
模拟等待,执行异步睡眠/延迟。
您可能还想在async
/ await
上阅读更多内容。有几个很好的Channel9视频; Stephen Toub,Eric Lippert和许多其他微博博客都有很好的概述。 Jon Skeet的“eduasync”博客系列也非常适合真正深入。我和其他许多人一样写了an async intro on my own blog。
简而言之,async
和await
的实际工作原理如下:
async
关键字仅启用await
关键字。就这些。它不在后台线程上运行该方法。await
仅在其“awaiter”未完成时才异步行动。因此,在您的情况下,btnAsync01_Click
和slowMethodAsync
都在UI线程上运行。 slowMethodAsync
将同步运行(执行Thread.Sleep
),然后返回btnAsync01_Click
,等待已完成的任务。由于任务已经完成,btnAsync01_Click
只是继续执行而不会屈服于UI消息循环。
如果将Thread.Sleep
替换为await TaskEx.Delay
,则btnAsync01_Click
将开始在UI线程上运行,并将调用slowMethodAsync
(也在UI线程上运行)。当slowMethodAsync
await
延迟(未完成)时,它会将未完成的任务返回btnAsync01_Click
。 btnAsync01_Click
将await
该任务(未完成),并将返回到UI循环。
当延迟到期时,它将完成,slowMethodAsync
将恢复(在UI线程上)。 slowMethodAsync
完成后,其返回的任务将完成,btnAsync01_Click
将恢复(在UI线程上)。