【问题标题】:Handling exception per task, using WhenAny使用WhenAny处理每个任务的异常
【发布时间】:2018-10-19 14:00:47
【问题描述】:

我试图弄清楚如何正确处理一个“坏”Task 引发的异常,当在 throttling patternWhenAny 中实现多个任务时。

不幸的是,我不断收到所有“好”任务引发的异常,该异常在一个“坏”任务引发异常后完成。

我已尝试添加 ContinueWith 以尝试让剩余的“好”任务返回正确的值。然而,即便如此,“好”任务仍然坚持仍然抛出异常。

如何编写代码以确保处理一个“坏”任务的异常,同时从其他“好”任务中获取正确的值?

这里有一个简化的例子来演示这个问题。

这会模拟抛出异常或返回良好结果的代码。在这种情况下,只有当输入是 int 2 时才会抛出异常:

static class Bar {
    public static string MightThrowException(int i) {
        if (i == 2) throw new Exception("bad error: " + i.ToString());
        // if not 2, just return input
        return i.ToString();
    }
}

...这是应该为该实例处理异常的代码:

public async Task<string> TestThrottle() {
    var tasks = new List<Task<string>>();
    var results = new List<string>();

    // mock the 'priming' that occurs in a throttling pattern
    tasks.Add(Task.Run(() => Bar.MightThrowException(0)));

    // begin throttling, for an additional 4 tasks
    for (var i = 1; i < 5; i++) {
        try {
            var task = await Task.WhenAny(tasks);
            results.Add(task.Result);
            tasks.Remove(task);
        }
        catch (Exception ex) {
            results.Add("handled " + ex.Message);
        }
        tasks.Add(Task.Run(() => Bar.MightThrowException(i)));
    }

    return string.Join("\n", results);
}

整个事情都是以这种方式在 Main() 中触发的:

Task.Run(() => {
    string result = new Foo().TestThrottle().Result;
    System.Diagnostics.Debug.WriteLine(result);
}).Wait();

【问题讨论】:

  • 仅供参考,这是针对 .NET 4.6.2 的。同样,当我在catch 中处理AggregateExceptionInnerExceptions 并输出内部异常消息时,它会验证异常'bad error: 2' 被多次捕获。

标签: c#


【解决方案1】:

您将获得任务的结果,如果任务出现故障,它将在您将其从列表中删除之前引发异常,这与链接中的代码不同,它等待任务之后 将其从列表中删除。这确保即使它出现故障,它也会从任务列表中删除。

还请注意,如果您只使用SemaphoreSlim 而不是拥有这样的任务列表,那么整个事情就会更加清晰。信号量的代码少得多,代码更清晰,代码更容易修改等等。

【讨论】:

  • 这是问题的主要部分。也感谢您指出 SemaphoreSlim 的选项,我将进一步探索
【解决方案2】:

抛出的行不在你的 try catch 中。

tasks.Add(Task.Run(() => Bar.MightThrowException(i)));

这就是将抛出的内容。编辑:Task.Run 立即排队并可能立即运行任务。您的 MightThrowException 方法应该返回一个任务。然后,您可以将该任务添加到您的列表中,它将按照您的预期在 try catch 中运行。对于一些额外的信息,我觉得这篇文章很有帮助

https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

【讨论】:

  • 这确实是问题的一部分 - 感谢您的指导
  • 我认为反对票是在我编辑之前。之前我说过它会立即开始,这是不正确的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-20
  • 2014-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-03
  • 1970-01-01
相关资源
最近更新 更多