我在主线程中创建一个任务来管理我的线程。我的目的是从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。
答案 0 :(得分:0)
首先,您必须在catch
方法的GenerateReport
块中重新抛出异常
public void GenerateReport()
{
var didwork = false;
try
{
...
}
catch (Exception e)
{
this.log.LogError(...);
throw; // Important!
}
finally
{
if (!didwork)
{
...
}
}
}
其次,你不应该在任务中使用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)
{
...
}
}