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的顶端,也就是事件处理函数。

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

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.

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.

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.

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

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

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

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

C# Async Await 注意事项的更多相关文章

  1. async/await的使用以及注意事项

    使用 async / await, 搭配 promise, 可以通过编写形似同步的代码来处理异步流程, 提高代码的简洁性和可读性. 本文介绍 async / await 的基本用法和一些注意事项. a ...

  2. async & await 异步编程的一点巧方法

    await 关键字不会创建新的线程,而是由Task任务或是FCL中的xxxAsync等方法创建的线程,而且这里创建的线程都是基于线程池创建的工作线程,属于后台线程. await关键字会阻塞/暂停调用它 ...

  3. async/await使用深入详解

    async和await作为异步模型代码编写的语法糖已经提供了一段时间不过一直没怎么用,由于最近需要在BeetleX webapi中集成对Task方法的支持,所以对async和await有了深入的了解和 ...

  4. Python 进阶 异步async/await

    一,前言 本文将会讲述Python 3.5之后出现的async/await的使用方法,我从上看到一篇不错的博客,自己对其进行了梳理.该文章原地址https://www.cnblogs.com/dhcn ...

  5. 异步编程之Async,Await和ConfigureAwait的关系

    在.NET Framework 4.5中,async / await关键字已添加到该版本中,简化多线程操作,以使异步编程更易于使用.为了最大化利用资源而不挂起UI,你应该尽可能地尝试使用异步编程.虽然 ...

  6. Async,Await和ConfigureAwait的关系

    [转自]https://mp.weixin.qq.com/s/h10V-FshGoaQUWFPfy-azg 在.NET Framework 4.5中,async / await关键字已添加到该版本中, ...

  7. 测试Promise与Async/await的基本使用

    想在项目中用, 发现自己不是很熟 promise基本使用 基本使用-思路 new Promise()返回了一个状态机 一个完全无法被外界影响的状态机 构造函数, 传入一个函数, 两个参数, 分别是re ...

  8. 异步编程新方式async/await

    一.前言 实际上对async/await并不是很陌生,早在阮大大的ES6教程里面就接触到了,但是一直处于理解并不熟练使用的状态,于是决定重新学习并且总结一下,写了这篇博文.如果文中有错误的地方还请各位 ...

  9. 温故知新,CSharp遇见异步编程(Async/Await),聊聊异步编程最佳做法

    什么是异步编程(Async/Await) Async/Await本质上是通过编译器实现的语法糖,它让我们能够轻松的写出简洁.易懂.易维护的异步代码. Async/Await是C# 5引入的关键字,用以 ...

随机推荐

  1. Firemonkey ListView 点击事件

    Firemonkey ListView 的点击事件一直让人摸不着头绪(各平台触发规则不太相同),因为它提供了点击相关的事件就有如下: OnChange:改变项目触发. OnClick:点击触发. On ...

  2. sso demo mysql ( cas )

    基本配置 参考之前得随笔  http://www.cnblogs.com/rocky-fang/p/5354947.html 1. tomcat-cas 修改配置 1.1 在D:\test\sso\t ...

  3. C++析构函数调用异常问题研究

    最近又遇到一个奇葩问题,程序在自己的开发机器和某些机器上运行完好,但是在测试人员的几台机器上运行就直接推出了.开始以为是出现了野指针,因为delete野指针时程序会直接退出.代码翻来覆去过来即便确认没 ...

  4. python函数和常用模块(三),Day5

    递归 反射 os模块 sys模块 hashlib加密模块 正则表达式 反射 python中的反射功能是由以下四个内置函数提供:hasattr.getattr.setattr.delattr,改四个函数 ...

  5. [小北De编程手记] : Lesson 04 玩转 xUnit.Net 之 Fixture(下)

    上一篇文章<[小北De编程手记] : Lesson 03 玩转 xUnit.Net 之 Fixture(上)>向大家介绍了xUnit.Net 共享数据的方式.Test Case的构造函数 ...

  6. Java final类

    如果说整个类都是final(在它的定义前冠以final关键字),就表明自己不希望从这个类继承,或者不允许其他任何人采取这种操作.换言之,出于这样或那样的原因,我们的类肯定不需要进行任何改变:或者出于安 ...

  7. JavaScript学习(1):基础

    这篇文章里,我们来聊一些JavaScript的基础知识. 1. 如何运行JavaScript? JavaScript是一种解释型的语言,它不需要提前编译.通常情况下,JavaScript会放在网页中, ...

  8. [AngularJS] 使用AngularAMD动态加载Controller

    [AngularJS] 使用AngularAMD动态加载Controller 前言 使用AngularJS来开发Single Page Application(SPA)的时候,可以选用AngularU ...

  9. 与锤子手机HR的对话——创业没有联合创始人,CTO 等高管会把它当做自己的事业吗?

    以下对话,是在被之前的锤子HR磨叽2周约面试折腾的火大的心态下进行…… 这个问题发到知乎,被一群人骂啊……cnblogs都是工程师,估计懂期权参加创业的同学多一些,有空前往知乎声援一下……在这里:ht ...

  10. 类似 Dribbble 下载按钮的 SVG 弹性动画进度条

    Codrops 发布了一个如何创建一个基于弹性效果的 SVG 加载进度条教程,基于 SVG 和 TweenMax 实现.按钮开始的时候是一个带有箭头的图标,一旦它被点击,动画成一个有趣的小金属丝和一个 ...