在finally中调用一个需要await的方法

  最近在把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的方法

时间: 2024-08-01 17:09:15

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

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

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

Js文件中调用其它Js函数的方法

Js文件中调用其它Js函数的方法 在项目开发过程中,也许你会遇这样的情况.在某一Js文件中需要完成某一功能,但这一功能的大部分代码在另外一个Js文件中已经完成了,自己只需要调用这个方法再加上几句代码就可以实现所需的功能.我们知道,在html中,利用<script language="javascript" type="text/javascript" src="../script.js"></script>引入的两个js是

a 中调用js的几种方法

我们常用的在a标签中有点击事件:1. a href="javascript:js_method();" 这是我们平台上常用的方法,但是这种方法在传递this等参数的时候很容易出问题,而且javascript:协议作为a的href属性的时候不仅会导致不必要的触发window.onbeforeunload事件,在IE里面更会使gif动画图片停止播放.W3C标准不推荐在href里面执行javascript语句 2. a href="javascript:void(0);"

[转]vc中调用其他应用程序的方法(函数) winexec,shellexecute ,createprocess

三个SDK函数: WinExec,ShellExecute ,CreateProcess可以实现调用其他程序的要求,其中以WinExec最为简单,ShellExecute比WinExec灵活一些,CreateProcess最为复杂.    WinExec 两个参数,前一个指定路径,后一个指定显示方式.    ShellExecute 可以指定工作目录,并且还可以寻找文件的关联直接打开不用加载与文件关联的应用程序,ShellExecute还可以打开网页,启动相应的邮件关联发送邮件等等.    Cr

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

1 jquery ajax中支持哪些返回类型在JQuery中,AJAX有三种实现方式:$.ajax() , $.post , $.get(). 预期服务器返回的数据类型.如果不指定,jQuery 将自动根据 HTTP 包 MIME 信息来智能判断,比如 XML MIME 类型就被识别为 XML.在 1.4 中,JSON 就会生成一个 JavaScript 对象,而 script 则会执行这个脚本.随后服务器端返回的数据会根据这个值解析后,传递给回调 函数.可用值: •"xml": 返回

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

有时候需要调用一个web项目的jsp或者servlet,但是执行内部的代码,并不是打开jsp,例如需要在一段java代码中清除一个web项目中的缓存,那么可以把清除缓存的代码放在该web项目的一个servlet中,只需要执行如下代码: URL url = new URL("http://192.168.2.123:8080/sace/ClearCache"); url.openStream(); openStream() 执行一次相当于一次URL请求,其中url.openStream(

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

我们常用的在a标签中有点击事件:1. a href="javascript:js_method();" 这是我们平台上常用的方法,但是这种方法在传递this等参数的时候很容易出问题,而且javascript:协议作为a的href属性的时候不仅会导致不必要的触发window.onbeforeunload事件,在IE里面更会使gif动画图片停止播放.W3C标准不推荐在href里面执行javascript语句 2. a href="javascript:void(0);"

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

本文转自:http://www.jb51.net/article/37404.htm 1.system(执行shell 命令)相关函数 fork,execve,waitpid,popen表头文件 #include<stdlib.h>定义函数 int system(const char * string);函数说明 system()会调用fork()产生子进程,由子进程来调用/bin/sh-cstring来执行参数string字符串所代表的命令,此命令执行完后随即返回原调用的进程.在调用syst

Java中编写一个完美的equals方法

首先看下Java语言规范对equals方法的要求: 1,自反性,对于任何非控引用x,x.equals(x)都应该返回true. 2,对称性,对于任何引用x和y,如果x.equals(y)返回true,那么y.equals(x)也应该返回true. 3,传递性,如果x.equals(y),y.equals(z)都返回true,那么,x.equals(z)返回true. 4,一致性,如果x和y引用的对象没有发生变化,那么无论调用多少次x.equals(y)都返回相同的结果. 5,对于任意非空引用x,