C# Async Await 注意事项

Avoid Using Async Void  --- 避免使用async void

  • async void 只能用于事件处理函数。而且保证永远不在用户代码中调用这些事件处理函数。
  • async void 调用时,不能使用await,因此程序执行不会中止在调用处,而是立刻执行下面的语句,可能会引发意外的状况发生。
  • 在写被用户代码调用的函数时,永远使用async Task<T>、async Task返回值类型的函数。
  • await func() 容许编译器把函数在await处拆分红两部分。第一个部分在await调用处结束。第二部分使用await调用的结果(若是有返回值的话),而后从哪里开始执行。要使await关键词,函数的返回类型必须是Task类型。

Beware of Deadlocks --- 当心死锁

在某种程度上,异步方法具备传染行为。当要调用一个异步方法的时候,你必须让调用异步方法的方法也变成异步形式。这种形式一直重复,直到向上移动到call stack的顶端,也就是事件处理函数。app

若是这个路径中的某一个函数没法变成异步方式,这将引入一个问题。举例来讲:constructors,他们不能是异步的。因此你不能在它的函数体中使用await。这时,有两个处理方式,一个是把要调用的函数变为async void形式,可是正如上一节所说的,这将让咱们没有办法再await这个方法。另外一种方式是咱们经过调用返回的Task的Wait()函数,或者读它的Result属性,来同步的等待函数执行完成。固然,同步的代码会暂时中止应用处理消息队列,这是咱们最初使用异步函数所要解决的问题,这在大多数状况下是坏主意。更糟糕的,在某些状况下,这将形成死锁。less

Any synchronously called asynchronous code in InnocentLookingClass constructor is enough to cause a deadlock:异步

public class InnocentLookingClass()
{
     public InnocentLookingClass()
     {
         DoSomeLengthyStuffAsync().Wait();
         // do some more stuff
     }
 
     private async Task DoSomeLengthyStuffAsync()
     {
         await SomeOtherLengthyStuffAsync();
     }
 
     // other class members
}

Let us dissect what is happening in this code.async

MyEventHandler synchronously calls InnocentLookingClass constructor, which invokesDoSomeLengthyStuffAsync, which in turn asynchronously invokes SomeOtherLengthyStuffAsync. The execution of the latter method starts; at the same time the main thread blocks at Wait untilDoSomeLengthyStuffAsync completes without giving control back to the main message loop.函数

Eventually SomeOtherLengthyStuffAsync completes and posts a message to the message queue implying that the execution of DoSomeLengthyStuffAsync can continue. Unfortunately, the main thread is waiting for that method to complete instead of processing the messages, and will therefore never trigger it to continue, hence waiting indefinitely.oop

As you can see, synchronously invoking asynchronous methods can quickly have undesired consequences. Avoid it at all costs; unless you are sure what you are doing, i.e. you are not blocking the main message loop.post

Allow Continuation on a Different Thread --- 容许在另外一个线程中继续

在返回的Task对象上调用ConfigureAwait(false);ui

这个方法能够避免死锁,尽管它没有办法解决【在异步调用完成以前阻塞消息循环】的问题。this

 

 

 

 

 

from http://www.dotnetcurry.com/csharp/1307/async-await-asynchronous-programming-examplesspa

相关文章
相关标签/搜索