Here Eric Lippert说:
无法等待返回异步方法的void;这是一场“火与... 忘记“方法。 它确实异步工作 ......
它确实可以异步工作吗?
为了测试它,我制作了一个Windows窗体应用程序并处理了一个任意事件。在处理程序内部,我开始进行大量计算。显然,它会阻止UI响应:
t= Test.unscoped.new; t.successful
=> true
我在Eric的回答中缺少什么?
答案 0 :(得分:13)
Eric的答案中我错过了什么?
我的意思是它像任何其他异步方法一样工作。当您在异步方法中等待某些东西时,该方法的其余部分将被注册为等待事物的继续。无论异步方法是否无效,都是如此。
在您的示例中,您的代码与返回任务的异步方法完全相同。尝试更改方法以返回任务,并且您将看到它的行为完全相同。
记住," async"并不意味着"我在另一个线程上同时运行"。这意味着"该方法可以在其动作完成之前返回"。它在行动完成之前可以返回的点标有" await"。你还没有用"等待"标记任何东西。
我怀疑你相信异步需要并发的神话。再次:异步只是意味着方法可以在其工作完成之前返回。你开始煮一些鸡蛋,门铃响,你去门廊的包装,你完成煮鸡蛋,你打开包。 "煮鸡蛋"并且"获取邮件"作业不是并发 - 您从未同时同时。它们是异步。
答案 1 :(得分:6)
所有async
关键字都允许您等待方法中的异步操作(并将结果包装在任务中)。
每个异步方法都会同步运行,直到达到第一个await。如果您没有等待任何事情,那么此方法(无论是返回任务还是不返回任务)将同步运行。
如果您的方法是同步的,通常根本不需要使用async await。但是如果你想将CPU密集型操作卸载到另一个线程,那么UI线程很长时间都不会被阻塞,你可以使用Task.Run
:
await Task.Run(() => CPUIntensiveMethod());
答案 2 :(得分:5)
只有async
的分配方法才能使其异步调用。对于异步调用,需要使用await
关键字进行方法调用 body < /强>
关于这个:
无法等待返回异步方法的void;这是一场火灾和火灾 忘记&#34;方法。它确实异步工作......
这意味着您无法在其他方法中等待 THIS 方法。
await Form1_KeyPressed(this, EventArgs.Empty)
要使代码正常工作,您需要一个await
关键字的方法,如:
private async void Form1_KeyPressed(object sender, EventArgs e)
{
for(int i=0; i<int.max; i++)
;
// In the body some code like this
await YourMethod();
}
更新版本
“异步”关键字
“async”关键字在应用于方法时的作用是什么?
当您使用“async”关键字标记方法时,您实际上是在告诉编译器两件事:
在方法上使用“async”关键字是否强制该方法的所有调用都是异步的?
没有。当您调用标记为“async”的方法时,它会在当前线程上开始同步运行。 因此,如果您有一个返回void的同步方法,并且您要做的就是将其标记为“async”,那么该方法的调用仍将同步运行。无论您是否离开,都是如此返回类型为“void”或将其更改为“Task”。类似地,如果你有一个返回一些TResult的同步方法,你所做的就是将它标记为“async”并将返回类型更改为“Task”,那么该方法的调用仍然会同步运行。
将方法标记为“async”不会影响方法是同步还是异步运行。相反,它使该方法能够分成多个部分,其中一些部分可以异步运行,这样该方法可以异步完成。这些部分的边界只能在使用“await”关键字显式编码的情况下发生,因此如果在方法的代码中根本不使用“await”,则只有一个部分,因为该部分将开始运行同步地,它(以及它的整个方法)将同步完成。
有关详情,请参阅此处:
http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/async-await-faq.aspx
答案 3 :(得分:3)
Async / await允许您创建可以异步运行的代码。它甚至可以并行运行(与异步正交)。但是,它是否并行运行取决于您的任务的安排方式。
当您从UI或ASP.NET上下文调用代码时(更具体地说,来自这些框架中具有UI控件的上下文中的主线程,因为大多数控件只能在拥有它们的线程上访问),默认情况下不会安排到后台线程。您仍将看到代码的执行将在继续之前等待Task完成,但由于Task被调度到同一(主)线程,因此它将阻止该线程上的任何其他操作(例如,处理UI事件)。
如果你知道你的代码在后台线程中是安全的(再次,这通常是因为你知道你不访问任何线程仿射的控件属性),你可以覆盖使用ConfigureAwait安排行为:
<div id="word_content">
<br>Testing Time: 2015-10-29 17:57:11<br>
Total Age: 19<br>
Total Friemd: 9<br>
Total Family: 10<br>
<br>
Here are the suggestions - Him_530037_: <a href="www.mytarget.com="_blank">93358546</a>
<h3>Overview</h3><br>
<ul>
<li>(The overlap provided is not good)</li>
</ul>
<h3>Structure</h3><br>
<h4>Target:</h4><br>
<ul>
<li>Audience.</li>
<li>Lookalike</li>
<li>Overlap of Audience</li>
<a href="https://www.myPage.com/lolPagess/?id=06" target="_blank">06<font name="names" hidden="" style="display: inline;"> - Page Likes</font></a>
</ul>
另请参阅:Async/Await - Best Practices in Asynchronous Programming
答案 4 :(得分:1)
Async只是一个声明,您可以使用异步方法。如果你要创建一个像
这样的任务private async Task<int> callMe()
{
int i;
for(i = 0; i<int.max; i++)
;
return i;
}
您可以在KeyPressed事件中使用 await callMe(); 行运行代码。当然,您不必返回任何值,但这只是一个实际的例子。
答案 5 :(得分:0)
仅仅因为你声明一个方法async
并不能让它自动在另一个线程中运行
你必须自己用Task.Run()
开始一个。
所以在你的情况下,这将是:
private async void Fomr1_KeyPressed(object sender, EventArgs e)
{
await Task.Run(() => {
for(int i=0; i<int.max; i++);
});
}
async/await
的一些好起点:
Asynchronous Programming with Async and Await
Parallel Programming with .NET
Task Schedulers
答案 6 :(得分:0)
我从CLS Compilance发现这个解释非常有启发性:
现在记住
await
后的所有内容非常重要 关键字在延续中执行。使用之间的区别await
和ContinueWith
是继续实际上是在 调用者线程,在这种情况下是UI线程。
所以:
private async void Form1_KeyPressed(object sender, EventArgs e)
{
// ----------------------> Surely, on UI thread
await Something(); ------> (May be) on new thread
// ----------------------> Surely, on UI thread
for(int i=0; i<int.max; i++)
;
}