等待异步任务,而不在AggregateException中包装异常 [英] Wait for async Task without wrapping exceptions in AggregateException

查看:75
本文介绍了等待异步任务,而不在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();
}

通常,将awaitWait()结合使用是一个坏主意(它可能导致死锁),但这是正确的解决方案.

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 throws AggregateException 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 Tasks that were created using the Task constructor. That's not the case here, so you can't use it. Tasks returned from async methods are always already started.

这篇关于等待异步任务,而不在AggregateException中包装异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆