合并异步方法的结果并同步返回

本文关键字:同步 返回 结果 异步方法 合并 | 更新日期: 2023-09-27 17:50:44

我读过很多帖子,人们面临着类似的问题,但他们似乎做出了不适用的假设,或者他们的代码根本不适合我。我需要组合来自异步方法的结果。唯一异步的东西,我想要的是结果的组合。由于Azure服务总线一次只允许我抓取256条消息,所以我想发送多个请求,以便一次获得几批消息,并将其放入一个列表。

似乎有一个假设,如果你正在调用异步方法,您希望在工作完成时返回给调用方(例如:一些长时间运行的任务)。然而,我一点也不想那样。我我想等任务完成后再拿我的合并列表并返回。

首先,我不想用async标记我的调用方法。我可以,但为什么我应该,我通过调用一个同步方法,碰巧执行一些异步操作之前返回给我。

我见过使用WhenAll()然后处理结果的例子,但这对我不起作用。我尝试了所有不同的排列,但它要么锁定我的应用程序,要么告诉我任务尚未执行。

这是我目前的内容:

public IEnumerable<BrokeredMessage>[] GetCombinedResults()
{
            var job = () => ServiceBus.TrackerClient.ReceiveBatchAsync(BatchLimit);
            Task<IEnumerable<BrokeredMessage>> task1 = _retryPolicy.ExecuteAsync<IEnumerable<BrokeredMessage>>(job);
            Task<IEnumerable<BrokeredMessage>> task2 = _retryPolicy.ExecuteAsync<IEnumerable<BrokeredMessage>>(job);
            IEnumerable<BrokeredMessage>[] results = Task.WhenAll<IEnumerable<BrokeredMessage>>(task1, task2).Result;
            return results;
}

但是调用结果会导致它被锁定。我读到过这样做可能会导致死锁,但在其他问题中也看到过这种建议。如果我调用Task.WaitAll()并且不关心结果,这种类型的设置工作得很好。不确定为什么当我想从任务返回结果时这变得困难。我试过使用Task。运行,然后在得到结果之前退出我的方法。

合并异步方法的结果并同步返回

您似乎对使用异步进行扇出并行感兴趣。这样做是完全合理的。为了利用扇形输出的并行性,没有必要使整个调用链异步。

你绊倒了通常的ASP。净僵局。您可以使用Task.Run作为一种简单的、故障安全的方法来避免它。首先,让我们将GetCombinedResults设置为异步,以保持简单和一致:

public async Task<IEnumerable<BrokeredMessage>[]> GetCombinedResultsAsync()
{
            var job = () => ServiceBus.TrackerClient.ReceiveBatchAsync(BatchLimit);
            Task<IEnumerable<BrokeredMessage>> task1 = _retryPolicy.ExecuteAsync<IEnumerable<BrokeredMessage>>(job);
            Task<IEnumerable<BrokeredMessage>> task2 = _retryPolicy.ExecuteAsync<IEnumerable<BrokeredMessage>>(job);
            IEnumerable<BrokeredMessage>[] results = await Task.WhenAll<IEnumerable<BrokeredMessage>>(task1, task2);
            return results;
}

这个方法显然是正确的。它不会混合同步和异步。这样调用:

var results = Task.Run(() => GetCombinedResultsAsync()).Result;

这个工作的原因是GetCombinedResultsAsync执行没有同步上下文。