惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Engineering at Meta
Engineering at Meta
博客园_首页
H
Help Net Security
WordPress大学
WordPress大学
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
B
Blog
I
InfoQ
SecWiki News
SecWiki News
T
Tailwind CSS Blog
Spread Privacy
Spread Privacy
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
Vulnerabilities – Threatpost
N
Netflix TechBlog - Medium
P
Palo Alto Networks Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Vercel News
Vercel News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
K
Kaspersky official blog
M
MIT News - Artificial intelligence
S
Schneier on Security
T
Threat Research - Cisco Blogs
F
Fortinet All Blogs
Cyberwarzone
Cyberwarzone
Scott Helme
Scott Helme
aimingoo的专栏
aimingoo的专栏
Martin Fowler
Martin Fowler
MyScale Blog
MyScale Blog
The Cloudflare Blog
Recent Announcements
Recent Announcements
Security Latest
Security Latest
G
GRAHAM CLULEY
IT之家
IT之家
Y
Y Combinator Blog
The Last Watchdog
The Last Watchdog
腾讯CDC
Google DeepMind News
Google DeepMind News
V
V2EX
S
Securelist
TaoSecurity Blog
TaoSecurity Blog
B
Blog RSS Feed
S
SegmentFault 最新的问题
博客园 - 叶小钗
P
Proofpoint News Feed
云风的 BLOG
云风的 BLOG
Project Zero
Project Zero
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
F
Full Disclosure

博客园 - 山不转水转...

Windbg的First chance exception WPF 文本框焦点导致的内存泄露问题 产品功能被像素级抄袭了。我们拿什么来保护原创的产品设计? 显示器文字发虚的一种原因 HttpClient + IIS压缩动态内容 Windows 上第一款全局轮盘菜单软件(鼠标党进) MVC6的内置ActionResult类型 将long数字序列化为json时,转换为字符串 共享一个在线代码片段收集服务 清除ASPX页面中的meta:resourceKey="[a-zA-Z0-9]+" MVC 多语言记录1 设置默认的ResourceType knockoutjs with绑定导致unobtrusive validation失效的问题 查询SQL Server中所有数据库的数据文件位置 那些年,我做共享软件(3)完结 那些年,我做共享软件(2) 那些年,我做共享软件(1) URTracker事务跟踪系统在软件企业中的应用 浅析缺陷管理系统URTracker 问题跟踪软件URTracker和Windows域的集成
C# Async Await 注意事项
山不转水转... · 2016-10-07 · via 博客园 - 山不转水转...

2016-10-07 16:18  山不转水转...  阅读(1450)  评论()    收藏  举报

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();

    }

    private async Task DoSomeLengthyStuffAsync()

    {

        await SomeOtherLengthyStuffAsync();

    }

}

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