C# 如何并行执行多个异步调用?

C# 如何并行执行多个异步调用?,c#,asynchronous,C#,Asynchronous,我有许多命令可以调用soapweb服务(betfairapi)。都是经典的异步编程模型类型 public void DoXXX( <input parameters ...> ) { XXXRequest Request = new XXXRequest(); // populate Request from input parameters ... BetfairService.BeginXXX( Request, XXXCallback, State );

我有许多命令可以调用soapweb服务(betfairapi)。都是经典的异步编程模型类型

public void DoXXX( <input parameters ...> )
{
    XXXRequest Request = new XXXRequest();
    // populate Request from input parameters ...
    BetfairService.BeginXXX( Request, XXXCallback, State );
}

private void XXXCallback(IAsyncResult Result)
{
    XXXResponse Response = BetfairService.EndXXX(Result);
    if (Response.ErrorCode == XXXErrorCode.OK)
        // store data from Response
    else
        // deal with error
}
public void DoXXX()
{
XXXRequest=新的XXXRequest();
//从输入参数填充请求。。。
betfailservice.BeginXXX(请求,xxx回调,状态);
}
私有void XXXCallback(IAsyncResult结果)
{
XXXResponse-Response=BetfairService.EndXXX(结果);
if(Response.ErrorCode==XXXErrorCode.OK)
//存储来自响应的数据
其他的
//处理错误
}
我想执行一组指定的命令,然后在所有命令完成后,使用组合返回的数据值进行一些计算

我可以按顺序执行此操作,方法是创建一个命令队列,让每个回调方法在完成后触发队列中的下一个命令,并将计算作为队列中的最后一项。然而,这是相对缓慢的

我的理想解决方案是让所有这些命令并行运行,然后在所有命令完成后触发计算。我试过查看Task.Factory.fromsync(),但我能找到的所有示例都只包括对BeginXXX/EndXXX的直接调用,而没有对响应执行任何操作


是否有人有任何针对此问题的合适解决方案的指针?

要使用
fromsync
,您需要指定返回类型:

var task = Task<XXXResponse>.Factory.FromAsync( ...
var task=task.Factory.fromsync(。。。
然后,您将有一个任务,其
结果
属性类型为
XXXResponse

然后您可以使用
Parallel.Invoke
并行运行初始命令。这将阻止所有这些任务完成。然后您可以执行“附加处理”

或者,您可以将初始任务存储在一个数组中,并使用
Task.Factory.continuewhalll
创建一个延续


尼克

你应该有一个已执行服务调用的计数器。在每个回调方法中,你应该检查这个计数器-如果它等于服务调用的最大数量,你应该做额外的处理,否则-你只需增加计数器。

我建议你看看微软的反应式扩展(Rx)它允许您将异步操作(除其他外)转换为可观察的LINQ查询

假设我有三个函数,每一个都需要花费大量的时间来计算:

Func<int> fa = () =>
{
    Thread.Sleep(2000);
    return 42;
};

Func<int, string, string> fb = (n, t) =>
{
    Thread.Sleep(n * 1000);
    return t + n.ToString();
};

Func<DateTimeOffset> fc = () =>
{
    Thread.Sleep(1000);
    return DateTimeOffset.UtcNow;
};
现在,我只需执行以下操作即可启动所有呼叫:

IObservable<int> oa = ofa();
IObservable<string> ob = ofb(1, "foo");
IObservable<DateTimeOffset> oc = ofc();
然后我订阅此查询以获得结果:

query.Subscribe(p =>
{
    Console.WriteLine(p.a);
    Console.WriteLine(p.b);
    Console.WriteLine(p.c);
});
在我的测试中,我在这段代码周围放置了计时器来计算实际的执行时间。即使如果以串行方式运行,那么总时间应该是4秒,但这段代码在2分钟内完成——这是三个时间中的最长时间

现在这个例子只是Rx可以做的一个小方面,但它是一个很好的起点

如果我能进一步解释的话,大声喊出来

以下是Rx的链接:


如果我使用Task.Factory.continuewhalll,有没有办法强迫它等到所有回调实际完成处理,而不是仅仅被调用?我不完全确定你在问什么。从
Task.Factory.fromsync
返回的任务应该在
EndXXX
方法完成后才能完成eted.
continuewheall
还返回一个
Task
对象,您可以对其执行所有正常的任务操作,如
Wait()
。实际上这是我的错误。我正在为WPF开发,因此所有可能更新绑定属性的内容都包装在CurrentDispatcher.BeginInvoke()中-这就是导致我的排序问题的原因。任务不需要这样做,而且一切正常。谢谢提示。
var query =
    from a in oa
    from b in ob
    from c in oc
    select new { a, b, c };
query.Subscribe(p =>
{
    Console.WriteLine(p.a);
    Console.WriteLine(p.b);
    Console.WriteLine(p.c);
});