【问题标题】:Canceling task if a parallel task throw an exception如果并行任务抛出异常则取消任务
【发布时间】:2019-02-12 08:07:08
【问题描述】:

我有两个共享相同取消令牌的并行任务,客户端要求两个结果列表,例如:

class ResponseDTO
{
    public IEnumerable<Entity1> Entity1List { get; set; }
    public IEnumerable<Entity2> Entity2List { get; set; }
}

这两个请求是同时计算和依赖的,因此如果列表中的一个没有结果,则无需等待另一个结果。

var cts = new CancellationTokenSource();
var token = cts.Token;

Task task1 = new Task(() =>
{
    //fetch Entity1 results into entity1List

    if (!entity1List.Any())
    {
        cts.Cancel();
    }
    else
    {
        responseDTO.Entity1List = entity1List;
    }
}, token);

Task task2 = new Task(() =>
{
    //fetch Entity2 results into entity2List

    if (!entity2List.Any())
    {
        cts.Cancel();
    }
    else
    {
        responseDTO.Entity2List = entity2List;
    }
}, token);

task1.Start();
task2.Start();

try
{
    Task.WaitAll(new[] { task1, task2 }, token);
}
catch (OperationCanceledException oce)
{
    return responseDTO;
}
catch (AggregateException ae)
{
    foreach (var ex in ae.InnerExceptions)
        //Log the exception
    return responseDTO;
}

return responseDTO;

如果任务返回一个空列表,取消工作正常。

我的问题是:如果另一个任务抛出一般异常,如何取消其中一个任务?

【问题讨论】:

  • 如果发生异常,您可以请求取消,然后在另一个任务查询toke.IsCancelationRequested...
  • 我问的是监控其他异常(不是取消异常)
  • 您可以在//fetch 代码中引入try/catch 块并在catch 中调用cts.Cancel();
  • 将单个取消令牌传递给所有任务,然后在 catch 块中取消该取消令牌,这将中止仍在执行的其他任务,假设您已正确编写代码以获取取消令牌考虑在内。
  • 正如@LasseVågsætherKarlsen 所说,如果有取消任务的代码,任务一旦启动就不会自动取消。您必须自己实现该代码。

标签: c# multithreading task-parallel-library


【解决方案1】:

已通过@noobed 评论解决。

try
{
    //fetch Entity1 results into entity1List
}
catch
{
    cts.Cancel();
}

一般的异常会被catch,cts可以用cancel调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-05
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多