c# - 按顺序运行任务 : how to deal with exceptions?

标签 c# async-await

根据 svick 的建议我创建了一个小类,其目的是按顺序运行任务,也就是说,它在 ThreadPool 上安排它们,但它确保它们按照提交的顺序一个接一个地执行。它看起来像这样:

class SequentialTaskRunner<TResult> where TResult : new() {

    public Task<TResult> Run(Func<TResult> func) {
        var result = RunInternal(func, m_previous);
        m_previous = result;
        return result;
    }

    async Task<TResult> RunInternal(Func<TResult> func, Task<TResult> previous) {
        await previous;
        return await Task.Run(func);
    }

    Task<TResult> m_previous = Task.FromResult(new TResult());
}

现在,我遇到的问题是,如果 func() 抛出异常,那么 Run() 的每次后续调用也将返回该异常,并且无法运行新任务。我试过像这样更改 RunInternal:

async Task<TResult> RunInternal(Func<TResult> func, Task<TResult> previous) {
    if (previous.Exception == null) {
        await previous;
    }
    return await Task.Run(func);
}

但这并不可靠;如果快速提交任务,一个任务的失败仍然会导致多个任务返回相同的异常。我对为什么感到困惑,并希望得到解释。我刚刚开始使用 async/await 顺便说一句。

最佳答案

您的代码之所以不起作用,是因为您几乎是在要求它预测 future 。

Task 尚未完成时,其 Exception 将始终为 null。这意味着您的 await previous 很可能会抛出异常。

这里最简单的解决方案是使用通用的catch:

async Task<TResult> RunInternal(Func<TResult> func, Task<TResult> previous)
{
    try
    {
        await previous;
    }
    catch {}

    return await Task.Run(func);
}

如果您想隐藏那个空的 catch(因为这通常是一种不好的做法),或者如果您经常这样做并希望避免重复,您可以为此编写一个辅助方法:

public static async Task IgnoreException(this Task task)
{
    try
    {
        await task;
    }
    catch {}
}

用法:

async Task<TResult> RunInternal(Func<TResult> func, Task<TResult> previous)
{
    await previous.IgnoreException();
    return await Task.Run(func);
}

关于c# - 按顺序运行任务 : how to deal with exceptions?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22273055/

相关文章:

c# - sub linq 查询使这需要很长时间,我怎样才能使它更快?

c# - 如何等待引发 C# 事件?

c# - MahApps.Metro 找不到资源

c# - Progress<T> 没有报告功能

c# - RegisterWaitForSingleObject 与 System.Timers

c# - 异步方法上的 Task.Wait() 在本地工作,但不能通过其他方法工作

c# - 在 C# 中,我应该使用 string.Empty 或 String.Empty 或 ""来初始化字符串?

c# - 只有当所有异步操作都完成时,我怎样才能让我的应用程序继续运行?

c# - Open 和 OpenAsync 之间的区别 (SqlConnection)

c# - 从属性 setter 调用异步方法