等待异步任务,而不在AggregateException中包装异常 [英] Wait for async Task without wrapping exceptions in AggregateException
问题描述
我正在使用一个提供以...Async
结尾并返回Task
的方法的库.我将在命令行应用程序中使用它们.所以我需要经常同步调用它们.
I am using a library which provides methods ending with ...Async
and return Task
. I am going to use these in a command line application. So I need to call them synchronously a lot.
C#当然不允许在Main
方法中调用这些方法,因为您不能在Main
方法上使用async
修饰符.假设这是任务:
C# of course does not allow calling these methods in Main
method since you cannot use async
modifier on Main
method. Assume this is the task:
var task = datastore.Save(data);
我发现了几种解决方案,例如:
I found several solutions like:
Tasks.WaitAll(task);
task.Wait();
但是在AggregateException
中所有这些包装引发的异常,我不想要.我只想说task.Result
,我希望会抛出原始异常.
however all these wrap thrown exceptions in AggregateException
, I don't want that. I just want to say task.Result
and I expect the original exception to be thrown.
当我使用返回Task<TResult>
的方法时,即使未设置任何连续任务,task.Result
也会抛出AggregateException
.为什么会这样?
When I use a method returning Task<TResult>
, task.Result
throws AggregateException
even though there are no continuation tasks set. Why is this hapening?
我也尝试过
task.RunSynchronously();
它给出了错误:
在未绑定到委托的任务(例如从异步方法返回的任务)上,可能不会调用RunSynchronously.
RunSynchronously may not be called on a task not bound to a delegate, such as the task returned from an asynchronous method.
所以我想这不适用于标记为async
的方法.
so I guess that's not for methods marked as async
.
在没有异步上下文的控制台应用程序中使用为异步应用程序设计的库的模式的任何想法吗?
Any ideas on patterns using libraries designed for async apps in console apps where there is no asynchronous context?
推荐答案
我将在命令行应用程序中使用它们.因此,我需要同步调用它们.
I am going to use these in a command line application. So I need to call them synchronously a lot.
不,你不知道.您可以 在控制台应用程序中使用async
-await
,您只需要在顶部进行异步即可同步转换.您可以使用Wait()
:
No, you don't. You can use async
-await
in a console application, you just need to make an async to sync transition at the very top. And you can do that by using Wait()
:
public static void Main()
{
MainAsync().Wait();
}
public static async Task MainAsync()
{
var datastore = …;
await datastore.SaveAsync();
}
通常,将await
与Wait()
结合使用是一个坏主意(它可能导致死锁),但这是正确的解决方案.
Usually, combining await
with Wait()
is a bad idea (it can cause deadlocks), but it's the right solution here.
请注意,如果SaveAsync()
引发异常并且您没有捕获到该异常,则它将从Wait()
中重新抛出为AggregateException
.但是您可以将其作为MainAsync()
中的原始异常捕获(因为它不使用Wait()
).
Note that if SaveAsync()
throws an exception and you don't catch it, it will be rethrown as AggregateException
from the Wait()
. But you can catch it as the original exception in MainAsync()
(because it doesn't use Wait()
).
如果您真的想直接抛出第一个异常,则可以执行与await
相似的操作:task.GetAwaiter().GetResult()
.请注意,如果Task
包含多个异常,则只会得到第一个异常(但对await
也是如此).
If you really wanted to get the first exception thrown directly, you could do something similar to what await
does: task.GetAwaiter().GetResult()
. Note that if the Task
contains more than one exception, you will get only the first one (but the same applies to await
).
从C#7.1开始,您可以将Main
方法设置为async
,编译器将为您编写转换代码:
Since C# 7.1, you can make your Main
method async
and the compiler will write the transition code for you:
public static async Task Main()
{
var datastore = …;
await datastore.SaveAsync();
}
当我使用返回
Task<TResult>
的方法时,即使未设置任何连续任务,task.Result
也会抛出AggregateException
.为什么会这样?
When I use a method returning
Task<TResult>
,task.Result
throwsAggregateException
even though there are no continuation tasks set. Why is this happening?
这与延续无关.单个Task
可以表示多个操作,并且每个操作都可以引发异常.因此,Task
方法总是抛出包装在AggregateException
中的异常.
This has nothing to do with continuations. A single Task
can represent multiple operations, and each of them can throw an exception. Because of that, Task
methods always throw the exceptions wrapped in an AggregateException
.
我也尝试过
task.RunSynchronously()
那没有任何意义. RunSynchronously()
只能在使用Task
构造函数创建的Task
上使用.这里不是这种情况,因此您不能使用它.从异步方法返回的Task
总是已经启动.
That doesn't make any sense. RunSynchronously()
can only be used on Task
s that were created using the Task
constructor. That's not the case here, so you can't use it. Task
s returned from async methods are always already started.
这篇关于等待异步任务,而不在AggregateException中包装异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!