事件无async修饰,怎么用await

 我来答
若以下回答无法解决问题,邀请你更新回答
潮荃让5010
2017-06-22 · TA获得超过1096个赞
知道小有建树答主
回答量:1070
采纳率:57%
帮助的人:193万
展开全部
相对于之前Begin/End模式和事件模式,async/await模式让程序员得以用同步的代码结构进行异步编程。async/await入门很方便,但是深入理解却涉及很多领域,如线程池、同步上下文等等。我断断续续接触了几个月,稍微有一些心得:
await的作用是等待异步Task完成,并不是阻塞的。举个例子,一个异步方法:<pre t="code" l="csharp">public async Task Caller()
{
Action0();
await Method();
Action3();
}

public async Task Method()
{
Action1();
await Task.Delay(1000);
Action2();
}A. 当你在非UI线程A上执行Caller(),将完成以下几件事:
[线程A]执行Action0()
[线程A]调用await Method()
[线程A]执行Action1()
[线程A]启动任务Task.Delay(1000),并在线程池里安插一个新任务,在Task.Delay(1000)完成后,由另一个线程执行6
[线程A]去处理别的事情
[线程B]执行Action2()
[线程B]await Method()返回
[线程B]执行Action3()</ol> 其中,线程A和线程B并不保证是同一个线程。如果你在await前后打印线程ID,你会发现ID是不同的。
B. 当你在UI线程上执行Caller(),过程有了变化:

[UI线程]执行Action0()
[UI线程]调用await Method()
[UI线程]执行Action1()
[UI线程]启动任务Task.Delay(1000),并在线程池里安插一个新任务,在Task.Delay(1000)完成后,由另一个线程执行6
[UI线程]去处理别的事情
[线程C]在UI线程的同步上下文中执行7(类似于在窗体类上执行Invoke()方法)
[UI线程]执行Action2()
[UI线程]await Method()返回
[UI线程]执行Action3()</ol> 可见,当使用await方法的线程为UI线程时,程序默认会通过第6步,保证await前后是同一个线程ID。这个当然是有一定性能牺牲的(甚至会造成死锁,在D里会讨论),如果你不想在await完成后回到UI线程,见C。
C. 你可以在UI线程上使用await XXX().ConfigureAwait(false)去替代await XXX(),来禁止当await XXX()结束时恢复线程。举个例子,执行下列代码是没问题的(如B里描述的):<pre t="code" l="csharp">private async void button1_Click(object sender, EventArgs e)
{
this.Text = "123";
await Task.Delay(1000);
this.Text = "321";
}但是,执行下列代码就会发生“线程间操作无效”的错误:<pre t="code" l="csharp">private async void button1_Click(object sender, EventArgs e)
{
this.Text = "123";
await Task.Delay(1000).ConfitureAwait(false);
this.Text = "321"; //线程间操作无效
}因为执行<pre t="code" l="csharp">this.Text = "321";的线程已经不再是UI线程。

D. 顺便一提,Task.Wait()方法,相比于await Task,会同步地执行Task。但是,如果你在UI线程上Wait的Task里本身又有await,那么将会产生死锁:<pre t="code" l="csharp">private void Foo(object sender, EventArgs e)
{
this.Text = "123";
Method().Wait(); //此处发生死锁
this.Text = "321"; //这行永远也不会执行
}
private async Task Method()
{
await Task.Delay(1000);
} 为什么呢?Method().Wait()会阻塞UI线程等待Method()完成,但是参照B过程,在await完成后,Method()完成前,是需要恢复到UI线程的,但是此时UI线程已经被阻塞了,因此死锁就发生了。 要避免这个死锁,可以参照C。
E. 说出来你可能不信,上面的都是我手打的。在内容上虽然不一定严谨,但希望对楼主和其它新接触TAP的朋友有一定启发。
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式