[英]I want the Task to handle any exceptions that are thrown, but am finding it difficult to stop them from reaching the parent
我正在.NET 4.0中的Web Hook上工作,該Web Hook將異步運行lambda,然后在完成后將結果發布到給定的URI。
我已經做到了,但是現在我希望Task處理所有拋出的異常,並且發現很難阻止它們到達父級。
這是我的代碼的一部分:
private readonly Func<T> _startTask;
private readonly string _responseUri;
public Task<T> Begin()
{
var task = new Task<T>(_startTask);
task.ContinueWith<T>(End);
task.Start();
return task;
}
private T End(Task<T> task)
{
if (task.IsFaulted)
{
return HandleException(task);
}
var result = task.Result;
WebHookResponse.Respond(result, _responseUri);
return result;
}
private T HandleException(Task<T> task)
{
WebHookResponse.HandleException(task.Exception.InnerException, _responseUri);
return null;
}
我嘗試過的另一種版本調用ContinueWith()
兩次,以注冊一個延續以運行OnlyOnRanToCompletion
而另一個則運行OnlyOnFaulted
。 (我不確定兩次調用ContinueWith()
是否正確。):
public Task<T> Begin()
{
var task = new Task<T>(_startTask);
task.ContinueWith<T>(End, TaskContinuationOptions.OnlyOnRanToCompletion);
task.ContinueWith<T>(HandleException, TaskContinuationOptions.OnlyOnFaulted);
task.Start();
return task;
}
private T End(Task<T> task)
{
var result = task.Result;
WebHookResponse.Respond(result, _responseUri);
return result;
}
private T HandleException(Task<T> task)
{
WebHookResponse.HandleException(task.Exception.InnerException, _responseUri);
return null;
}
因此,基本上,我希望每個任務都可以通過延續函數處理自己的異常。 就目前而言,在上述兩個示例中都從未調用過HandlException延續函數。
我在測試用例中引起異常,我應該提到我正在使用Tasks.WaitAll(tasks);
在進行我的斷言之前,請調用一系列任務以確保所有任務均已完成,並且我不確定該調用是否對任務處理異常的方式有所不同。 當前,WaitAll引發一個AggregationException,該異常會聚合每個Task的異常,因為HandleException連續函數沒有處理這些異常。
觀察任務異常的任務延續不會處理該異常。 每當您等待任務完成時,它仍然會發生。
您說您在斷言之前正在調用WaitAll(tasks)。 我敢打賭,如果您給它足夠的時間,您的延續將可以運行,但是WaitAll()上的異常通常會在繼續運行之前發生。 因此,您的斷言可能在您的延續有機會完成其工作之前就失敗了。
我使用這種方法是因為它提供了一種很好的聲明性流利的編碼風格,並且不會在異常處理方面使您的代碼亂七八糟。
class Program
{
static void Main()
{
Task.Factory.StartNew(
() =>
{
throw new Exception();
})
.Success(() => Console.WriteLine("Works"))
.Fail((ex) => Console.WriteLine("Fails")).Wait();
Console.ReadKey();
}
}
public static class TaskExtensions
{
public static Task Success(this Task task, Action onSuccess)
{
task.ContinueWith((t) =>
{
if (!t.IsFaulted)
{
onSuccess();
}
});
return task;
}
public static Task Fail(this Task task, Action<Exception> onFail)
{
return task.ContinueWith(
(t) =>
{
if (t.IsFaulted)
{
t.Exception.Handle(x => true);
onFail(t.Exception.Flatten());
}
});
}
}
也許,對於Henk Holterman的回答, 順序有所不同。 那是,
var task = new Task<T>(_startTask);
task = task.ContinueWith<T>(HandleException, TaskContinuationOptions.OnlyOnFaulted);
task = task.ContinueWith<T>(End, TaskContinuationOptions.OnlyOnRanToCompletion);
task.Start();
將確保HandleException將在必要時運行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.