static async void Main(string[] args)
{
Task t = new Task(() => { throw new Exception(); });
try
{
t.Start();
t.Wait();
}
catch (AggregateException e)
{
// When waiting on the task, an AggregateException is thrown.
}
try
{
t.Start();
await t;
}
catch (Exception e)
{
// When awating on the task, the exception itself is thrown.
// in this case a regular Exception.
}
}
Run Code Online (Sandbox Code Playgroud)
在TPL中,当在Task中抛出异常时,它被包装为AggregateException.
但是使用await关键字时也不会发生同样的情况.
这种行为的解释是什么?
c# exception-handling parallel-extensions task-parallel-library async-await
等待故障任务(具有异常集的任务)时,await将重新抛出存储的异常.如果存储的异常是a AggregateException,它将重新抛出第一个并丢弃其余的异常.
我们如何使用await并同时抛出原件AggregateException以便我们不会意外丢失错误信息?
注意,当然可以考虑使用hacky解决方案(例如,试一试await,然后调用Task.Wait).我真的希望找到一个干净的解决方案.这里最好的做法是什么?
我想过使用自定义awaiter,但内置TaskAwaiter包含很多魔法,我不知道如何完全重现.它调用TPL类型的内部API.我也不想重现所有这些.
如果你想玩它,这是一个简短的repro:
static void Main()
{
Run().Wait();
}
static async Task Run()
{
Task[] tasks = new[] { CreateTask("ex1"), CreateTask("ex2") };
await Task.WhenAll(tasks);
}
static Task CreateTask(string message)
{
return Task.Factory.StartNew(() => { throw new Exception(message); });
}
Run Code Online (Sandbox Code Playgroud)
只抛出两个例外中的一个Run.
请注意,Stack Overflow上的其他问题无法解决此特定问题.建议重复时请小心.
根据一些文章和博客,如下所示的代码应该导致.NET 4中的异常
static void Main(string[] args)
{
Task.Factory.StartNew(() => { throw new Exception(); });
Thread.Sleep(1000);
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("Completed");
}
Run Code Online (Sandbox Code Playgroud)
预期例外:
未处理的异常:System.AggregateException:通过等待任务或访问其Exception属性未观察到任务的异常.结果,终结器线程重新抛出了未观察到的异常.---> System.InvalidOperationException:由于对象的当前状态,操作无效.
但它没有.我的PC上的.NET 4应用程序就像.NET 4.5一样:
<ThrowUnobservedTaskExceptions enabled ="true"/>
看起来.NET 4已被修补以获得与.NET 4.5相同的行为.它是真的还是我的配置有些麻烦?或者,如果安装了4.5,任何.NET4应用程序(不针对4.5)都会以这种方式运行?提前致谢.
当使用lambdas时,通常是在TPL上,我会因缩进而迷失...是否有一些最佳实践来格式化?例如,请使用以下代码:
Task t1 = factory.StartNew(() =>
{
DoSomething();
}
.ContinueWith((t2) =>
{
DoSomethingWhenComplete();
}, TaskContinuationOptions.OnlyOnRanToCompletion)
).ContinueWith((t3) =>
{
DoSomethingOnError();
}, TaskContinuationOptions.OnlyOnFaulted);
Run Code Online (Sandbox Code Playgroud)
我想知道在被丢弃的任务抛出的情况下会发生什么?
示例:SendMailAsync 抛出异常会发生什么情况?
我需要担心/处理它吗?(即安全问题、内存泄漏或其他问题......)
async SendMailAsync(){ ... long process that throws an exception...}
Method(){
//_ = is discard as opposed to await
_ = SendMailAsync();
}
Run Code Online (Sandbox Code Playgroud) 是否可以从某个方法返回任务,该方法先调用多个Task<T>返回方法,然后返回某种类型,该类型包括先前调用的结果而无需使用await?
例如,以下内容很简单:
public Task<SomeType> GetAsync() => FirstOrDefaultAsync();
Run Code Online (Sandbox Code Playgroud)
但是,我想做这样的事情:
public Task<SomeType> GetAsync()
{
var list = GetListAsync(); // <-- Task<List<T>>
var count = GetCountAsync(); // <-- Task<int>
return new SomeType // <-- Obviously compiler error
{
List /* <-- List<T> */ = list, // <-- Also compiler error
Count /* <-- int */ = count, // <-- Also compiler error
};
}
Run Code Online (Sandbox Code Playgroud)
是否可以这样做而无需编写:
public async Task<SomeType> GetAsync()
{
return new Type2
{
List = await GetListAsync(),
Count …Run Code Online (Sandbox Code Playgroud)