在以下示例中抛出异常时,我似乎无法弄清楚为什么我的任务不处于故障状态(假设engine.Send(...)抛出异常):
var receiverTask = new Task<Task>(async () => {
result = await Task.FromResult(engine.Send(someObject));
});
receiverTask.Start();
receiverTask.Wait();
如果我在receiverTask.IsFaulted
之后receiverTask.Wait()
返回false,而不是我想象的那样。
我一直在读,我需要使用类似下面的结构:
receiverTask.ContinueWith(t => { /* error handling */ },
TaskContinuationOptions.OnlyOnFaulted);
但我似乎无法弄清楚如何将其整合到示例代码中。我是否在Start()之前调用它?在Wait()之前?
我希望调用程序能够以某种方式意识到receiverTask已抛出异常并失败。有什么指针吗?
答案 0 :(得分:2)
如果我正确理解了这种情况,您可以省略.Start()
并稍微使用.Wait()
。
(我不知道你的engine.Send(someObject)
方法是什么,所以我必须假设。)
让我们说你的方法返回一个bool(它没关系,但只是写下来。
如果是同步的,则返回的任务可以是:
Task<bool> receiverTask = Task<bool>.Run(async () =>
await Task<bool>.FromResult(engine.Send(someObject)));
或
Task<bool> receiverTask = Task.Factory.StartNew(async delegate
{
bool _result = await Task<bool>.FromResult(engine.Send(someObject));
return _result;
}, TaskScheduler.Default).Unwrap();
如果它是异步的,则返回的Task可以是:
Task<bool> receiverTask = Task.Run(async () =>
await engine.Send(someObject));
或
Task<bool> receiverTask = Task.Factory.StartNew(async delegate
{
bool _result = await engine.Send(someObject);
return _result;
}, TaskScheduler.Current).Unwrap<bool>();
(但是,如果没有其他异步/等待声明,所有这些都会阻塞。)
安排完任务后,可以定义一些延续条件来评估其状态
如果任务处于某种错误状态(已取消,已中止等),则其.IsCompleted
属性报告true
,但.Status
属性不是TaskStatus.RanToCompletion
。
receiverTask.ContinueWith(t =>
{
//Continue on faulted
Console.WriteLine(receiverTask.GetAwaiter().IsCompleted);
if (receiverTask.IsFaulted)
Console.WriteLine(receiverTask.Exception.InnerExceptions[0].Message);
}, TaskContinuationOptions.OnlyOnFaulted).Wait(0);
receiverTask.ContinueWith(t =>
{
//Continue on canceled
Console.WriteLine(receiverTask.GetAwaiter().IsCompleted);
if (receiverTask.IsCanceled)
Console.WriteLine(receiverTask.Exception.InnerExceptions[0].Message);
}, TaskContinuationOptions.OnlyOnCanceled).Wait(0);
receiverTask.ContinueWith(t =>
{
//Standard behaviour
Console.WriteLine(receiverTask.GetAwaiter().IsCompleted);
Console.WriteLine(receiverTask.Status.ToString());
}, TaskContinuationOptions.None).Wait();
//This writes only if no errors have been raised
if (receiverTask.Status == TaskStatus.RanToCompletion)
Console.WriteLine("Completed: {0} Result: {1}", receiverTask.GetAwaiter().IsCompleted, receiverTask.Result);
但您也可以使用Try / Catch块:
try
{
receiverTask.Wait();
if (receiverTask.Status == TaskStatus.RanToCompletion)
Console.WriteLine("Completed: {0} Result: {1}", receiverTask.GetAwaiter().IsCompleted, receiverTask.Result);
}
catch (Exception)
{
receiverTask.ContinueWith(t =>
{
//With continuation
if (receiverTask.IsFaulted)
Console.WriteLine(receiverTask.Exception.InnerExceptions[0].Message);
}, TaskContinuationOptions.OnlyOnFaulted);
//or without
//if (receiverTask.IsCanceled)
//Console.WriteLine(receiverTask.Exception.InnerExceptions[0].Message);
}