假设你有2async
方法定义如下:
public async Task<TResult> SomeMethod1()
{
throw new Exception();
}
public async Task<TResult> SomeMethod2()
{
await Task.Delay(50);
throw new Exception();
}
如果在这两种方法上
await
,行为将几乎相同。但如果你得到了任务,行为就不同了。如果我想缓存这样的计算结果,但只在任务运行到完成时。
我必须处理两种情况:
第一种情况:
public Task<TResult> CachingThis1(Func<Task<TResult>> doSomthing1)
{
try
{
var futur = doSomthing1()
futur.ContinueWith(
t =>
{
// ... Add To my cache
},
TaskContinuationOptions.NotOnFaulted);
}
catch ()
{
// ... Remove from the pending cache
throw;
}
}
第二种情况
public Task<TResult> CachingThis2(Func<Task<TResult>> doSomthing)
{
var futur = SomeMethod2();
futur.ContinueWith(
t =>
{
// ... Add To my cache
},
TaskContinuationOptions.NotOnFaulted);
futur.ContinueWith(
t =>
{
// ... Remove from the pending cache
},
TaskContinuationOptions.OnlyOnFaulted);
}
现在,我将执行计算以缓存的方法传递给缓存系统。
cachingSystem.CachingThis1(SomeMethod1);
cachingSystem.CachingThis2(SomeMethod2);
显然,我需要在“
ConinueWith
on faulted”和catch块中复制代码。你知道有没有办法让异常在等待之前或之后的行为相同吗?
最佳答案
SomeMethod1
和SomeMethod2
所需的异常处理没有区别。它们的运行方式完全相同,异常将存储在返回的任务中。
这个例子很容易看出这一点;
static void Main(string[] args)
{
try
{
var task = SomeMethod1();
}
catch
{
// Unreachable code
}
}
public static async Task SomeMethod1()
{
throw new Exception();
}
在这种情况下,不会处理任何异常,因为返回的任务未被等待。
但是,简单的
Task
返回方法和async
方法之间存在区别:public static Task TaskReturning()
{
throw new Exception();
return Task.Delay(1000);
}
public static async Task Async()
{
throw new Exception();
await Task.Delay(1000);
}
您可以通过在单个
async
块中使用同时调用该方法和await
返回任务的try-catch
包装器方法来避免代码重复:public static async Task HandleAsync()
{
try
{
await TaskReturning();
// Add to cache.
}
catch
{
// handle exception from both the synchronous and asynchronous parts.
}
}