【问题标题】:Managing thread exception using a Task使用任务管理线程异常
【发布时间】:2015-12-28 04:31:00
【问题描述】:

我正在我的主线程中创建一个任务来管理我的线程。我的目的是从 AggregateException 中受益,因此我希望我的任务在任务中启动的线程中发生异常时返回该异常,如下面的代码块所示。

public void ReportGeneratorFiveThreadTest()
{
    var logger = new Log4NetLogger(typeof(ReportGeneratorThreadTest));
    var tasks = new List<Task>();

    for (var i = 0; i < 1; i++)
    {
        var estimatedReportSize = EstimatedReportSize.Normal;
        var thread = new ReportGeneratorThread(logger, new ReportGenerator(20), estimatedReportSize);
        var task = Task.Factory.StartNew(
        () =>
        {
            thread.Start();                    
        });
        tasks.Add(task);
    }

    try
    {
       Task.WaitAll(tasks.ToArray());
       Debug.WriteLine("Tasks are completed");
    }
    catch (AggregateException e)
    {
        foreach (var v in e.InnerExceptions)
        {
            Debug.WriteLine(e.Message + " " + v.Message);
        }
    }
} 

GenerateReport() 方法被启动的线程调用并抛出该方法中定义的异常。

public void GenerateReport()
{
    var didwork = false;
    try
    {
        didwork = this.reportGenerator.GenerateReport(this.estimatedReportSize);
    }
    catch (Exception e)
    {
        this.log.LogError(ReportGenerator.CorrelationIdForPickingReport, string.Format(CultureInfo.InvariantCulture, "System"), string.Format(CultureInfo.InvariantCulture, "Error during report generation."), 0, e);
    }
    finally
    {
        if (!didwork)
        {
            Thread.Sleep(Settings.Default.ReportGenerationInterval);
        }
    }
}

问题是任务中没有出现异常,因此在这种情况下不会发生聚合异常。是否可以呈现这个innerexception,它发生在任务中的线程中,因此触发了聚合异常?

更新----------

我修改了以下代码:

 public void Start()
 {
        this.running = true;
        this.t = Task.Run(
        () =>
        {
            this.GenerateReport();
        });
        try
        {
            Task.WaitAny(this.t);
        }
        catch (AggregateException e)
        {
            foreach (var v in e.InnerExceptions)
            {
                Debug.WriteLine(e.Message + " " + v.Message);
            }
        }
 }

并与:

  public void GenerateReport()
    {
        var didwork = false;            
        try
        {
            didwork = this.reportGenerator.GenerateReport(this.estimatedReportSize);                
        }
        catch (Exception e)
        {
            this.log.LogError(ReportGenerator.CorrelationIdForPickingReport, string.Format(CultureInfo.InvariantCulture, "System"), string.Format(CultureInfo.InvariantCulture, "Error during report generation."), 0, e);
            throw new InvalidOperationException("Failed");
        }
        finally
        {
            if (!didwork)
            {
                Thread.Sleep(Settings.Default.ReportGenerationInterval);
                throw new InvalidOperationException("Failed");
            }
        }
    }

即使在 GenerateReport() 方法中抛出了 InvalidOperationException,它仍然没有捕获 AggregateException。

【问题讨论】:

  • 捕获并记录后抛出异常。即 GenerateReport 需要实际抛出。或者,GenerateReport 实际上可以返回一些东西(即 null 或异常),您可以拥有 Task 并遍历返回值。
  • 这也无济于事。似乎主线程在线程抛出异常之前完成了 Tasks.WaitAll 方法
  • 在您的“外部”创建任务和 GenerateReport 方法之间有我们看不到的代码,我猜如果没有发布完整的代码链,您正在其他地方捕获。

标签: c# .net task threadpool


【解决方案1】:

首先您必须在GenerateReport 方法的catch 块中重新抛出异常

public void GenerateReport()
{
    var didwork = false;
    try
    {
        ...
    }
    catch (Exception e)
    {
        this.log.LogError(...);
        throw; // Important!
    }
    finally
    {
        if (!didwork)
        {
            ...
        }
    }
}

其次,您不应该在 Task 中使用 Thread。仅使用任务

public void ReportGeneratorFiveThreadTest()
{
    var tasks = new List<Task>();

    for (var i = 0; i < 1; i++)
    {
        var task = Task.Factory.StartNew(() =>
        {
            // No need thread here
            GenerateReport();
        });
        tasks.Add(task);
    }

    try
    {
        ...
    }
    catch (AggregateException e)
    {
        ...
    }
}

【讨论】:

    猜你喜欢
    • 2015-03-10
    • 1970-01-01
    • 2013-09-21
    • 2022-10-26
    • 2021-05-01
    • 1970-01-01
    • 2019-08-20
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多