等待多个异步调用完成?

3

我需要从一个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();
}

非常感谢任何建议,因为我现在不知道该怎么做了。

谢谢大家。


1
你的异步调用方法签名是什么?另外,你说:“但它现在仍然在等待所有调用完成后才继续执行下一段代码”,这不正是你想要的吗? - Yuval Itzchakov
那是一个打字错误 - 对此我感到抱歉。我的意思是说它在继续执行下一段代码之前“不会”等待所有调用完成。在查看生成的调用时,它们都被设置为void。(我希望我正确理解了你的问题) - BrewingDev
我假设异步方法的方法签名是void返回的? - Yuval Itzchakov
1
清楚明白点,这是 [tag:c#],对吧? 如果是的话,请添加标签。如果不是,请添加另一个标签。它看起来像C#,但很可能是其他语言,其异步和等待的概念可能完全不同。 - Damien_The_Unbeliever
1个回答

8

建议重新构建带有异步调用功能的WCF客户端代理。目前,它正在使用旧模式,但如果您使用现代版的Visual Studio重新生成它,则应该可以得到更新的模式,它与async/await更兼容。

然后,您就可以直接使用await来进行WCF调用:

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应用程序。我是否完全错误地创建了代理? - BrewingDev
1
@SUCODev:我怀疑是 Xamarin 应用程序引起的问题。尝试创建一个常规的 PCL 或 .NET 4.5 dll,并在其上生成服务引用。 - Stephen Cleary
嗨@StephenCleary。您的解决方案似乎正是我正在寻找的,但我不确定如何注册和连接OnGotEventResult / OnGotLocationsResult / OnGotTypesResult。您是否愿意在您的答案中添加这些内容? - tinonetic
1
@user919426:我的答案使用TAP(async/await)方法,因此根本不使用那些事件。 - Stephen Cleary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接