【发布时间】:2017-10-13 11:20:04
【问题描述】:
我有一个应用程序被配置为捕获任何未观察到的任务异常,在 app.config 中启用 ThrowUnobservedTaskExceptions="true"。
我有一个库类(Class1),它需要在它的构造函数中启动一个异步任务,但在某些情况下会引发异常,并且当 Class1 的实例被释放时我会遇到 UnobservedTaskException 错误(因为该任务从未等待)。
我通过在构造函数中的任务上附加 ContinueWith 并在 TaskContinuationOptions 设置为 OnlyOnFaulted 的情况下处理异常(通过访问任务的 Exception 属性)来解决此问题,并且效果很好。
现在我遇到的问题是,这个异步任务(我在构造函数中初始化)也在这个类的方法中等待作为验证检查,以确保在继续执行方法中的其余代码之前完成任务。如果我在实例化我的类(Class1)之后调用了这个方法并且如果它抛出一个错误,我附加的 ContinueWith 将被执行并处理异常。我不想要这种行为。如果在方法中等待时导致错误,我希望它抛出异常。
我只希望仅针对这种情况处理未观察到的任务异常(而不是针对整个应用程序)——当 Class1 被初始化并且没有调用任何方法并且如果任务抛出异常时,我会在 ContinueWith 中处理它。我不希望在方法中等待此任务并且如果抛出异常时执行 ContinueWith 中的代码。
这里的代码将提供更清晰的信息。请让我知道是否有办法实现这一目标。
程序.cs
using (Class1 c = new Class1())
{
c.ValidateInitializeAsync().Wait(); // I want this to throw. Only if this line is commented, I want the exception to be handled.
}
// The application needs to be run in Release mode in order for GC to dispose c and enter into the scenario I want
while (true)
{
Thread.Sleep(100);
GC.Collect();
GC.WaitForPendingFinalizers();
}
Class1.cs
class Class1 : IDisposable
{
public Task initializeTask;
public Class1()
{
this.initializeTask = TaskHelper.InlineIfPossible(() => RunTask()).ContinueWith(t =>
{
Console.WriteLine(string.Format("Exception handled, {0}", t.Exception.HResult));
}, TaskContinuationOptions.OnlyOnFaulted);
}
public async Task ValidateInitializeAsync()
{
await this.initializeTask;
}
public async Task RunTask()
{
await Task.Run(() =>
{
Console.WriteLine("Running task...");
Task.Delay(5000).Wait();
throw new InvalidOperationException("exception occured");
});
}
public void Dispose()
{
Console.WriteLine("Class1 disposed.");
}
}
static class TaskHelper
{
static public Task InlineIfPossible(Func<Task> function)
{
if (SynchronizationContext.Current == null)
{
return function();
}
else
{
return Task.Run(function);
}
}
}
【问题讨论】:
标签: c# .net asynchronous task continuations