我有一项任务,如果发生异常,则取消使用sme cancelation令牌的任务并抛出异常:
var cancellationTokenSource = new CancellationTokenSource();
var task1 = Task.Factory.StartNew(
() =>
{
try
{
// Do work
}
catch (Exception exception)
{
cancellationTokenSource.Cancel();
// rethrow the error
throw;
}
},
cancellationTokenSource.Token,
TaskCreationOptions.None,
taskScheduler);
我有另一个task3(返回任务),它是task1和task2的延续,并使用相同的取消令牌:
return task3 =
Task.Factory.ContinueWhenAll(
new[] { task1, task2 },
tasks =>
{
// Do work
},
cancellationTokenSource.Token,
TaskContinuationOptions.None,
this.taskScheduler).Unwrap();
取消task1后,所有具有相同取消令牌的任务也会被取消。 我需要得到task1抛出的内部异常,它是如何完成的?
答案 0 :(得分:2)
如何使用async / await和常规异常处理?但它需要.NET 4.5。这样的事情(我不知道任务必须如何相互影响,所以你的代码可能看起来完全不同):
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
new MyClass().RunAsyncMethods();
Console.ReadLine();
}
public class MyClass
{
public async void RunAsyncMethods()
{
try
{
var cancellationTokenSource = new CancellationTokenSource();
var task1 = RunFirstTaskAsync(cancellationTokenSource);
var task2 = RunSecondTaskAsync(cancellationTokenSource);
await Task.WhenAll(task1, task2);
await RunThirdTaskAsync(cancellationTokenSource);
Console.WriteLine("Done");
}
catch (Exception exc)
{
Console.WriteLine(exc.Message);
}
}
public Task RunFirstTaskAsync(CancellationTokenSource cancelSource)
{
return Task.Run(() =>
{
try
{
Console.WriteLine("First Task is Running");
throw new Exception("Error happened in first task");
}
catch (Exception exception)
{
cancelSource.Cancel();
throw;
}
},
cancelSource.Token);
}
public Task RunSecondTaskAsync(CancellationTokenSource cancelSource)
{
return Task.Run(
() =>
{
Console.WriteLine("Second Task is Running");
},
cancelSource.Token);
}
public Task RunThirdTaskAsync(CancellationTokenSource cancelSource)
{
return Task.Run(
() =>
{
Console.WriteLine("Third Task is Running");
},
cancelSource.Token);
}
}
}
}
更新:我更新了代码以使用WhenAll。
UPDATE:更新了使用Task.Run方法创建任务的代码,而不是使用冷任务。
UPDATE:你可以省略async / await(尽管我认为这样更好)并且做一些老派的TPL错误处理。只是不对task3(返回任务)使用取消令牌,只针对它正在等待的任务。当它们完成时(通常,或通过异常/取消),你可以像这样处理task3中的异常:
// don't use the cancellation token for the third task as you used for the previous ones
var task3 = Task.Factory.ContinueWhenAll(
new[] { task1, task2 },
tasks =>
{
if (tasks[0].Exception != null)
{
tasks[0].Exception.Handle(exc =>
{
Console.WriteLine("First task failed :(");
return false; // signal that exception was handled, so it won't propagate
});
// add additional code here, or inside the Handle method above
}
if (tasks[1].Exception != null)
{
tasks[1].Exception.Handle(exc =>
{
Console.WriteLine("Second task failed :(");
return false; // signal that exception was handled, so it won't propagate
});
// add additional code here, or inside the Handle method above
}
// do the same for the rest of the tasks or iterate throught them with a foreach loop...
});