等待多个异步调用完成?

Posted

技术标签:

【中文标题】等待多个异步调用完成?【英文标题】:Waiting for multiple async calls to complete? 【发布时间】:2015-10-15 13:25:35 【问题描述】:

我必须从 WCF 服务调用三个不同的异步方法。我有以下包含所有三个调用的方法:

private async Task CreateMultipleTasksAsync()

    CrimcaseServiceClient client = new CrimcaseServiceClient(
        new BasicHttpBinding(),
        new EndpointAddress("http://192.168.1.100/FooService/FooService.svc")
        );

    client.GetEventCompleted += OnGotEventResult;
    client.GetEventAsync(eventInfo);

    client.GetLocationsCompleted += OnGotLocationsResult;
    client.GetLocationsAsync();

    client.GetTypesCompleted += OnGotTypesResult;
    client.GetTypesAsync();

三个调用都完成后,我需要填充一些值。但是,我似乎遇到了如何等待三个人先完成的问题。

我已经尝试这样做,使用这个调用,但它仍然没有等待所有调用完成,然后再继续下一段代码:

private void GrabData()

    var task = Task.Run(async () =>  await CreateMultipleTasksAsync(); );
    task.Wait();

任何建议都将不胜感激,因为我现在不知道该怎么做。

谢谢大家。

【问题讨论】:

异步调用的方法签名是什么?另外,您说:但它现在仍在等待所有调用完成,然后再继续执行下一段代码,这不正是您想要的吗? 那是一个错字 - 很抱歉。我的意思是说在继续下一段代码之前“不”等待所有调用完成。在查看生成的调用时,它们都设置为无效。 (希望我能正确理解您的问题) 我假设异步方法的方法签名是void返回? 说清楚 - 这是c#,对吧?如果是这样,请添加标签。如果不是,请添加一个不同的标签。它看起来像 C#,但很可能是其他语言,可能有非常不同的异步和等待概念。 【参考方案1】:

来自 WCF 服务

我建议您重建 WCF 客户端代理,启用异步调用。目前,它使用的是an older pattern,但如果您使用现代Visual Studio 版本重新生成它,它应该会生成一个newer pattern,它与async/await 配合使用效果更好。

那么您实际上可以在 WCF 调用中直接使用 await

private async Task CreateMultipleTasksAsync()

  CrimcaseServiceClient client = new CrimcaseServiceClient(
    new BasicHttpBinding(),
    new EndpointAddress("http://192.168.1.100/FooService/FooService.svc")
    );

  // Start the three asynchronous calls.
  var getEventTask = client.GetEventAsync(eventInfo);
  var getLocationsTask = client.GetLocationsAsync();
  var getTypesTask = client.GetTypesAsync();

  // Asynchronously wait (await) for them all to complete.
  await Task.WhenAll(getEventTask, getLocationsTask, getTypesTask);

  // Retrieve the results of the calls.
  var event = await getEventTask;
  var locations = await getLocationsTask;
  var types = await getTypesTask;

  // TODO: place OnGotEventResult / OnGotLocationsResult / OnGotTypesResult logic here

当您调用它时,您应该只使用await,而不是使用Task.RunTask.Wait

await CreateMultipleTasksAsync();
// At this point, the results have been retrieved and processed.

【讨论】:

Stephen Clearly - 非常感谢您的详细回复。我一直在使用 SvcUtil 来生成代理。因此,我删除了生成的文件,并直接通过 VS 将服务引用添加到我的项目中,但我得到“无法将类型 'void' 隐式转换为 'System.Threading.Tasks.Task'。这是在 Visual Studio 2013 中工作的一个 Xamarin PCL 应用程序。我只是创建代理完全错误吗? @SUCODev:我怀疑是 Xamarin 应用程序把它扔掉了。尝试创建常规 PCL 或 .NET 4.5 dll 并在其上生成服务引用。 嗨@StephenCleary。您的解决方案似乎正是我正在寻找的,但我不确定如何注册和连接 OnGotEventResult / OnGotLocationsResult / OnGotTypesResult。你愿意在你的答案中添加这个吗? @user919426:我的回答使用了 TAP (async/await) 方法,所以它根本不使用这些事件。

以上是关于等待多个异步调用完成?的主要内容,如果未能解决你的问题,请参考以下文章

在 XCTestCase 的 setUp() 中等待多个异步调用

异步IO和协程

同时等待多个具有独立延续的 WCF 异步调用

如何等待来自 forEach 循环的多个异步调用?

等待异步函数调用完成

有没有办法在异步函数中等待多个等待调用?