首页 文章

使用Task管理线程异常

提问于
浏览
0

我正在我的主线程中创建一个任务来管理我的线程 . 我的目的是从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);
        }
    }
}

问题是异常没有出现在任务中,因此在这种情况下不会发生聚合异常 . 是否有可能在任务的线程中出现这种不确定性,因此会触发aggregateexception?

UPDATE----------------------

我用以下代码修改了我的代码:

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 .

1 回答

  • 0

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

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

    其次,你不应该使用Thread inside Task . 仅使用任务

    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)
        {
            ...
        }
    }
    

相关问题