[英]Wait for async Task without wrapping exceptions in AggregateException
我正在使用一个库,它提供以...Async
结尾的方法并返回Task
。 我将在命令行应用程序中使用这些。 所以我需要大量同步调用它们。
C#当然不允许在Main
方法中调用这些方法,因为您不能在Main
方法上使用async
修饰符。 假设这是任务:
var task = datastore.Save(data);
我找到了几种解决方案,例如:
Tasks.WaitAll(task);
task.Wait();
然而,所有这些包装在AggregateException
抛出异常,我不想要那个。 我只想说task.Result
并且我希望抛出原始异常。
当我使用返回Task<TResult>
的方法时,即使没有设置继续任务, task.Result
抛出AggregateException
。 为什么会这样?
我也试过,
task.RunSynchronously();
它给出了错误:
RunSynchronously 不能在未绑定到委托的任务上调用,例如从异步方法返回的任务。
所以我想这不适用于标记为async
方法。
关于在没有异步上下文的控制台应用程序中使用为异步应用程序设计的库的模式的任何想法?
我将在命令行应用程序中使用这些。 所以我需要大量同步调用它们。
不,你没有。 您可以在控制台应用程序中使用async
- await
,您只需要在最顶部进行 async 以同步转换。 你可以通过使用Wait()
来做到这一点:
public static void Main()
{
MainAsync().Wait();
}
public static async Task MainAsync()
{
var datastore = …;
await datastore.SaveAsync();
}
通常,将await
与Wait()
结合是一个坏主意(它可能导致死锁),但这是正确的解决方案。
请注意,如果SaveAsync()
抛出异常而您没有捕获它,它将作为来自Wait()
AggregateException
抛出。 但是您可以将其作为MainAsync()
的原始异常MainAsync()
(因为它不使用Wait()
)。
如果您真的想直接抛出第一个异常,您可以执行类似于await
操作: task.GetAwaiter().GetResult()
。 请注意,如果Task
包含多个异常,您将只得到第一个(但同样适用于await
)。
从 C# 7.1 开始,您可以使Main
方法async
,编译器将为您编写转换代码:
public static async Task Main()
{
var datastore = …;
await datastore.SaveAsync();
}
当我使用返回
Task<TResult>
的方法时,即使没有设置继续任务,task.Result
抛出AggregateException
。 为什么会这样?
这与延续无关。 一个Task
可以代表多个操作,每个操作都可以抛出异常。 因此, Task
方法总是抛出包裹在AggregateException
的异常。
我也试过
task.RunSynchronously()
那没有任何意义。 RunSynchronously()
只能在使用Task
的是分别使用所创建的小号Task
构造。 这里不是这种情况,所以你不能使用它。 从异步方法返回的Task
总是已经启动。
您可以创建一个虚拟的Main
public static void Main()
{
MainAsync().Wait();
}
public static async Task MainAsync()
{
try {
var result = await dataStore.Save(data);
} catch(ExceptionYouWantToCatch e) {
// handle it
}
}
另外,请参阅此答案: https : //stackoverflow.com/a/9212343/1529246
从 C# 7.1 开始,您现在可以将 Main 方法声明为异步方法。 只需要确保您的语言设置为默认主要版本(现在应该在 VS 2019 中工作),或者您始终可以针对该语言的特定版本。
有关详细信息,请参阅此链接。 打开异步主
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.