最近在把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. IE7浏览器窗口大小改变事件执行多次bug(转)

    var resizeTimer = null; $(window).resize(function() { if (resizeTimer) clearTimeout(resizeTimer); re ...

  2. SharePoint 2013 User Profile Services之跨场发布

    在之前博客中已经描述了User Profile的两种配置场景,这篇博客将详细介绍微软官方推荐的配置方法. 测试环境的架构可以参考之前的博客内容,这里就不做介绍了,直接切入主题. 1. 在sp-farm ...

  3. Sharepoint学习笔记—习题系列--70-576习题解析 -(Q141-Q143)

    Question  141 You are planning an upgrade to a SharePoint 2010 application. You have the following r ...

  4. 【转】自定义UITableViewCell(registerNib: 与 registerClass: 的区别)

    自定义UITableViewCell大致有两类方法: 使用nib 1.xib中指定cell的Class为自定义cell类型(注意不是设置File's Owner的class) 2.调用 tableVi ...

  5. Android 学习心得 页面跳转,不显示新页面信息

    原因: 1.新页面的Activity中,public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceSt ...

  6. Android自定义ViewGroup,实现自动换行

    学习<Android开发艺术探索>中自定义ViewGroup章节 自定义ViewGroup总结的知识点 一.自定义ViewGroup中,onMeasure理解 onMeasure(int ...

  7. fillStyle图片填充

    图片自找 <!DOCTYPE HTML> <head> <meta charset = "utf-8"> <title>canvas ...

  8. Linux LVM学习总结——创建卷组VG

    在Linux平台如何创建一个卷组(VG)呢?下面简单介绍一下卷组(VG)的创建步骤.本文实验平台为Red Hat Enterprise Linux Server release 6.6 (Santia ...

  9. SQL Server删除distribution数据库二

    以前总结过一遍博文SQL Server删除distribution数据库,里面介绍了如何删除distribution数据库.今天介绍一个删除distribution的特殊案例, 在这之前,我不知道这个 ...

  10. 正则表达式解析URL

    正则表达式: var match = /^((ht|f)tps?:)\/\/([\w-]+(\.[\w-]+)*\/){1}(([\w-]+(\.[\w-]+)*\/?)*)?(\?([\w\-\., ...