在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>)返回Ta
sk,所以只需要⼀个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和async使用方法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,有可能⾥⾯是个异常!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。