最近在把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,有可能里面是个异常!

在finally中调用一个需要await的方法的更多相关文章

  1. 在C#中我们能调用一个类的私有方法吗

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:在C#中我们能调用一个类的私有方法吗.

  2. [Xcode 实际操作]九、实用进阶-(6)在Swift文件中调用Object-C的类和方法

    目录:[Swift]Xcode实际操作 本文将演示在Swift文件中调用Object-C的类和方法. 在项目文件夹[DemoApp]上点击鼠标右键 ->[New File]创建一个Object- ...

  3. jquery ajax中支持哪些返回类型以及js中判断一个类型常用的方法?

    1 jquery ajax中支持哪些返回类型在JQuery中,AJAX有三种实现方式:$.ajax() , $.post , $.get(). 预期服务器返回的数据类型.如果不指定,jQuery 将自 ...

  4. 如何在java代码中调用一个web项目jsp或者servlet

    有时候需要调用一个web项目的jsp或者servlet,但是执行内部的代码,并不是打开jsp,例如需要在一段java代码中清除一个web项目中的缓存,那么可以把清除缓存的代码放在该web项目的一个se ...

  5. a 标签中调用js的几种方法 文章摘自他人

    我们常用的在a标签中有点击事件:1. a href="javascript:js_method();" 这是我们平台上常用的方法,但是这种方法在传递this等参数的时候很容易出问题 ...

  6. a 标签中调用js的几种方法

    我们常用的在a标签中有点击事件: 1. a href="javascript:js_method();" 这是我们平台上常用的方法,但是这种方法在传递this等参数的时候很容易出问 ...

  7. a 中调用js的几种方法

    我们常用的在a标签中有点击事件:1. a href="javascript:js_method();" 这是我们平台上常用的方法,但是这种方法在传递this等参数的时候很容易出问题 ...

  8. a标签中调用js的几种方法

    1. a href="javascript:js_method();" 这是我们平台上常用的方法,但是这种方法在传递this等参数的时候很容易出问题,而且javascript:协议 ...

  9. 解析如何在C语言中调用shell命令的实现方法【转】

    本文转自:http://www.jb51.net/article/37404.htm 1.system(执行shell 命令)相关函数 fork,execve,waitpid,popen表头文件 #i ...

随机推荐

  1. 天津政府应急系统之GIS一张图(arcgis api for flex)讲解(十一)路径导航模块

    config.xml文件的配置如下: <widget label="路径导航" icon="assets/images/lujingdaohang.png" ...

  2. iOS 文件下载

    iOS 视频音乐类等应用会用到“文件下载”.文件下载在iOS中的实现如下: 1.小文件下载 @interface ViewController () <NSURLConnectionDataDe ...

  3. ArcSDE解除图层锁定

    SDE数据库用来共享.交互数据,比较好用,但经常被B/S那边锁定图层 ,导致不能编辑图层. 查看锁定是谁锁定了用户的命令: sdemon -o info -I users -i esri_sde 解决 ...

  4. UITableview中怎么找到每个cell

    一个朋友问我:我在每个cell中都添加了两个按钮(记为btnA和btnB),点击btnA时,对应的cell中添加一个子控件,再点击btnB时,对应的cell中的子控件就移除,怎么做到? 百度了一下,发 ...

  5. 【转载】ReactiveX 的理念和特点

    原作者地址:http://www.open-open.com/lib/view/open1440166491833.html ReactiveX是Reactive Extensions的缩写,一般简写 ...

  6. [转]完美洗牌(Perfect Shuffle)问题

    [转]原博文地址:https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/02.09.md ...

  7. Java调用solrj5.5.3接口,查询数据

    前期准备 搭建solr服务 参考上一篇,搭建solr搜索服务. 添加依赖 maven工程的话,添加如下依赖, <!-- https://mvnrepository.com/artifact/or ...

  8. 基于Windows 10平台的PM2.5检测器制作

    本篇文章详细讲解了如何利用SDS011激光式PM2.5传感器.HC-06蓝牙模块和Windows 10设备完成一个简单的PM2.5检测器及其应用程序的开发.该检测器使用蓝牙完成数据输出,方便设备连接, ...

  9. CMS本质上是什么

    2015-121.数据可以任意取和构造,结构也很自由,不一定是“站点-栏目-文章-评论”.2.主要用于显示,前台不产生数据(评论.浏览次数除外).3.在模版进行循环.判断,也比后台写代码要方便很多很多 ...

  10. 记录sql语句的执行记录,用于分析

    SET STATISTICS PROFILE ONSET STATISTICS IO ONSET STATISTICS TIME ONGO --这之间是要执行的脚本select * from [Use ...