假设你有2个async
方法定义如下:
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块中复制代码。
你是否知道是否有办法让异常在await之前或之后表现相同?
答案 0 :(得分:3)
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.
}
}
答案 1 :(得分:0)
除了I3arnon在他的回答中所说的,如果你在{em> async 方法ContinueWith
没有指定TaskContinuationOptions
的情况下,Task
捕获了异常您在延续处理程序中收到的参数可以通过以下方式处理:
SomeMethod1().ContinueWith(ProcessResult);
SomeMethod2().ContinueWith(ProcessResult);
使用ProcessResult
处理程序,如下所示:
private void ProcessResult<TResult>(Task<TResult> task)
{
if (task.IsFaulted)
{
//remove from cahe
}
else if (task.IsCompleted)
{
//add to cache
}
}