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

推荐订阅源

WordPress大学
WordPress大学
The GitHub Blog
The GitHub Blog
F
Fortinet All Blogs
Cloudbric
Cloudbric
P
Palo Alto Networks Blog
T
Threatpost
T
Tor Project blog
T
Tenable Blog
AWS News Blog
AWS News Blog
Project Zero
Project Zero
L
LangChain Blog
Cyberwarzone
Cyberwarzone
Engineering at Meta
Engineering at Meta
雷峰网
雷峰网
C
CERT Recently Published Vulnerability Notes
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Security Latest
Security Latest
云风的 BLOG
云风的 BLOG
I
Intezer
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
P
Proofpoint News Feed
A
Arctic Wolf
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Google DeepMind News
Google DeepMind News
V
Vulnerabilities – Threatpost
C
Cybersecurity and Infrastructure Security Agency CISA
MongoDB | Blog
MongoDB | Blog
aimingoo的专栏
aimingoo的专栏
K
Kaspersky official blog
Jina AI
Jina AI
N
News | PayPal Newsroom
T
The Blog of Author Tim Ferriss
D
DataBreaches.Net
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
博客园 - 【当耐特】
Hugging Face - Blog
Hugging Face - Blog
Recorded Future
Recorded Future
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
S
Secure Thoughts
TaoSecurity Blog
TaoSecurity Blog
P
Privacy & Cybersecurity Law Blog
P
Proofpoint News Feed
MyScale Blog
MyScale Blog
IT之家
IT之家
Forbes - Security
Forbes - Security
The Hacker News
The Hacker News
Last Week in AI
Last Week in AI
T
Threat Research - Cisco Blogs
Y
Y Combinator Blog

博客园 - Zhenway

Azure SignalR支持replication啦 Azure SignalR总览 定制json序列化 今天折腾这么一个正则 docfx组件介绍--YamlSerialization docfx daylybuild docfx开源啦 docfx组件介绍--MarkdownLite docfx预热中 合并批量请求 一个简单的Linq to TreeNode 当泛型方法推断,扩展方法遇到泛型类型in/out时。。。 4.5你太黑了,不带这么玩TypeForwardedTo的 一个非常简单的反射加速方案 加载时预防并发执行 又发现一个msdn的坑 又发现个.net framework的坑 sql server死锁神器 踩到一个Emit的坑,留个纪念
在finally中调用一个需要await的方法
Zhenway · 2014-08-20 · via 博客园 - Zhenway

  最近在把code改写成async+await的形式,发现有些情况下需要在finally中需要调用异步方法,但是编译器不允许在cache和finally中出现await关键字。。。但是用Wait()或者Result又会导致一些其他稀奇古怪的毛病(死锁啦,AggregateException啦。。。)

  所以,需要找一个类似于finally的效果,并且允许使用async..await的方式,想了一下,其实这不就是ContinueWith么!

  对没有返回值的try..finally可以用下面的方法:

public static async Task WithFinally(this Task tryCode, Func<Task, Task> finallyCode)
{
  await await tryCode.ContinueWith(finallyCode);
}

  为什么是await await?这个问题要说下ContinueWith的返回值了,ContinueWith(Action<Task>)返回Task,所以只需要一个await。而ContinueWith(Func<Task, TResult>返回的是Task<TResult>,这里TResult是Task,所以,返回值是Task<Task>,await Task<Task>,得到的是另一个Task,显然任务还没跑完,接着再等这个Task,就有了两个await了。

  来看下使用的示例:

async Task Sample()
{
   // do something ...
   await TryPart().WithFinally(async task =>
   {
      // do something ...
      await AsyncCallInFinally();
      // do something ...
   });
   // do something ...
}
Task TryPart()
{
   // ...
}
Task AsyncCallInFinally()
{
   // ...
}

  但是如果有TryPart返回值哪?于是我们需要这样的一个重载:

public static async Task<TResult> WithFinally<TResult>(this Task<TResult> tryCode, Func<Task<TResult>, Task> finallyCode)
{
   await await tryCode.ContinueWith(finallyCode);
   return await tryCode;
}

  这里假设finally部分不修改try部分的放回值。代码里除了之前的那个await await之外,又加了个return await tryCode,这里为什么要用await tryCode而不是用tryCode.Result哪?

  还记得前面说的那些稀奇古怪的毛病么?虽然这里用Result不可能出现死锁(前面的await await已经可以保证finallyCode执行完,finallyCode又是在tryCode完成后跑的,所以此时tryCode一定完成了),但是别忘了在出错的情况下,两者是有区别的,await tryCode会抛出原来tryCode中的异常,而tryCode.Result会抛出AggregateException。

  最后,finallyCode里面也要当心一个陷阱,不要随便看tryCode.Result,有可能里面是个异常!