webpack await 调试-探索异步/等待

小明使用async/await编写异步方法已经有好几年了,但他仍然没有完全理解上面的机制。 他决定向邻居小华请教。

听完小明的描述,小花说:首先你要明白异步的根源是什么? 异步的白话解释是:拉一个人(线程)帮忙做一些耗时的事情(下载、读写数据库等),我先做其他事情(退出线程),什么时候告诉我已经完成了。 继续做之前的事情(恢复上下文)。

见小花还是不明白,她说:我给你举个简单的例子,帮助你理解。 如果有两个方法A和B,A调用方法B,方法B是异步方法。 此时A不等待B执行完毕。 ,如图:

调试webpack_webpack await 调试_调试工程师

现在这两种方法被分成几个小块。 虽然使用await关键字来分隔同步和异步,但是方法的执行过程如下:

A调用方法B后,方法B在执行await之前仍然是同步方法。 例如,输出Sub1仍然在当前线程中执行。 当方法遇到await时,await后面的方法会在新的线程中执行。 当前线程退出函数,因为调用处没有await,主线程会继续执行并输出Part2,然后结束。 新线程中的Thread.Sleep(5000)执行完毕后,会执行到Console.Write("Sub2"); 这行代码会返回到原来的线程执行,虽然遇到await时会捕获当前线程的执行上下文。 给定一个新线程,执行完duration操作后,新线程会判断之前捕获的执行top和bottom是否为null。 如果没有,就会恢复并执行上下文中之前的方法,虽然是通过 Tak 的 ContineWith 方法注册反弹的,如图:

小明似乎明白了什么:现在方法A无需等待就调用DoSomethingAsync()。 如果方法A执行完之后需要这个方法继续执行,我们是不是应该在DoSomethingAsync()后面加上await呢? 小花回答是,并说:只要方法遇到await,前面的方法就会被新线程执行,然后线程退出去执行其他方法。 新线程执行完成后,会通知当前线程恢复上下文并继续执行,如图:

小明又问:你说异步方法执行完后,会在原来的线程中恢复执行下一个方法。 如果我想在新线程中继续执行剩余的代码怎么办? 小华说这个问题问得好。 当await调用新线程执行duration操作时,默认会捕获当前上下文。 如果不想捕获webpack await 调试,可以调用ConfigAwait(false)方法,如图:

执行过程如下:

小华补充说,网上提到的线索1、线索2、线索3等不一定准确。 由于异步反弹使用了线程池中的线程,所以反弹可能仍然在原来的线程中执行。 这主要取决于操作系统。 调度。

小明满意地点点头,问道:我经常听朋友说,使用异步方法会造成死锁。 为什么是这样? 小花听后说,他们调用异步方法的时候肯定是使用.Result(),如图:

小花指着图片解释道:前面的代码task.Result()会阻塞线程等待任务返回结果。 DoSomethingAsync 方法执行完 Thread.Sleep(5000) 后,发现捕获的上下文不为空,它会尝试使用 Console 行代码 .Write("Sub2") 交给调用线程进行执行。 此时调用线程还在等待,因此互相卡住,导致死锁,如图:

小明点点头,问道:如何预防? 小华表示,这样的情况也和框架有关。 为了让所有UI操作都在主线程中执行,WinForm添加了一个SynchronizationContext类实例来表示当前上下文。 在控制台等项目中,此 SynchronizationContext 实例默认为 null。webpack await 调试,所以即使使用.Result,也不会出现死锁。 但使用异步时最好不要使用.Result。 您可以使用 ConfigAwait(false) 来指示未捕获上下文,或者毕竟所有方法都是异步的。

小明听完,心满意足地回到了自己的小隔间。