这不是一个特定于语言的问题,但就我的具体情况而言,我使用的是C#。 (编辑:在进一步阅读之前,此问题的选定答案是特定于C#的语言)
我需要完成两个异步服务调用,然后从这两个回调中收集信息。由于代码生成器的性质,我基本上最终得到了我称之为" -Completed"使用服务调用的结果调用的事件处理程序。
因此,在这种情况下,我有两个单独的异步调用从两个不同的源收集数据。当他们完成后,我想合并数据,然后继续正常的工作流程。
所以,在C#样式的伪代码中:
MyAsyncServiceClient1 masc1 = new MyAsyncServiceClient1();
MyAsyncServiceClient2 masc2 = new MyAsyncServiceClient2();
masc1.MyCallCompleted += new EventHandler<MyCallCompletedEventArts>((sender, e) =>
{
.. collect some data ..
});
masc2.MyCallCompleted += new EventHandler<MyCallCompletedEventArts>((sender, e) =>
{
.. collect some more data ...
});
masc1.MyCall();
masc2.MyCall();
所以我的问题是,是否存在合并这样的异步回调的一般模式,以便我可以从两个回调中收集数据,然后使用组合数据执行某些操作?我的意思是,我知道有办法做到这一点。我过去曾设计过各种方法,但随着越来越多的异步编程,我发现这已经成为一种常见的模式,我想看看我是否能找到比定制解决方案更优雅,更通用的解决方案继续想出来。
答案 0 :(得分:3)
我们可以做的是编写一种方法将您的活动转变为Task
。 (这是您的某个类型的方法;您需要为每个事件创建这样的方法,除非两个类型都实现定义此事件的接口。)具有任务允许组合,聚合操作等使这样的问题更容易解决。
public static Task<MyCallCompletedEventArts> CallAsync(
this MyAsyncServiceClient1 client)
{
var tcs = new TaskCompletionSource<MyCallCompletedEventArts>();
EventHandler<MyCallCompletedEventArts> handler = null;
handler = (_, args) =>
{
tcs.TrySetResult(args);
client.MyCallCompleted -= handler;
};
client.MyCallCompleted += handler;
client.MyCall();
return tcs.Task;
}
(注意我们跳过一些箍以确保我们的处理程序在第一次触发后被删除。如果在您的情况下恰好没有必要,可以简化代码。)
现在你可以写:
MyAsyncServiceClient1 masc1 = new MyAsyncServiceClient1();
MyAsyncServiceClient2 masc2 = new MyAsyncServiceClient2();
var results = await Task.WhenAll(masc1.CallAsync(), masc2.CallAsync());
DoSomethingWithFirstClientsArgs(results[0]);