等待所有异步Web服务调用返回

时间:2011-11-03 13:50:38

标签: c# multithreading synchronization

我有一个桌面应用程序(.net 3.5),它使用经典的Web服务与服务器通信 我需要多次调用Web服务函数,等待它们全部完成,然后继续。

我想和平地做这些电话;显然我希望使用MyFunctionAsync方法 问题是 - 我不确定如何验证所有呼叫都已返回。我可能在这里错过了一些简单的同步机制。

这是我希望能够做到的:

public void DoWork()
{
   service.MyFuncCompleted+= MyFunc_Completed;
   foreach (var i in items)
   {
      service.MyFuncAsync(i);
      syncMechanism.WaitForAnother(1);  //signal that we have to wait for 1 more task to finish
   }
   syncMechanism.WaitForAllTasksToFinsih();  //wait until specified number of tasks have finished

   //continue
}

public void MyFunc_Completed(EventArgs e)
{
   //process result...
   syncMechanism.Signal(1);  //signal that 1 task has finished
}

任何人都知道这是c#?

2 个答案:

答案 0 :(得分:3)

这个(fork / join)在.NET 4中要容易得多,但你使用的是3.5,所以你必须采用老式的方式。

基本上,为每个操作递增一个计数器,然后在Completed处理程序中递减它。然后检查它是否已降为零,如果是,则表示等待句柄指示所有操作已完成。

以下是这个想法的一个例子:

static ManualResetEvent mre = new ManualResetEvent( false );
static int inFlight = 1; // start with 1 to fix race condition

static void DoWork()
{
    for ( int i = 0 ; i < 10 ; i++ )
    {
        var bw = new BackgroundWorker();

        bw.DoWork += bw_DoWork;
        bw.RunWorkerCompleted += bw_RunWorkerCompleted;

        Interlocked.Increment( ref inFlight );

        bw.RunWorkerAsync();
    }

    if ( Interlocked.Decrement( ref inFlight ) == 0 ) mre.Set();

    mre.WaitOne(); // this blocks until all workers have completed
}

static void bw_DoWork( object sender, DoWorkEventArgs e )
{
    Thread.Sleep( 1000 );
}

static void bw_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e )
{
    if ( Interlocked.Decrement( ref inFlight ) == 0 ) mre.Set();
}

答案 1 :(得分:0)

我会使用hashmap而不是简单的计数器,其中键是thread-id(或webservice名称,或者你能找到的任何易于处理的名称)。

作为值使用字符串或对象(表示调用时间)。

当给定的调用返回时,从散列映射中删除相应的项目。

当hashmap为空时,您知道可以继续。 如果它在很长一段时间后不是空的(这基本上是你所做的调用集合的超时),你可以在hashmap里面查看哪一个仍处于待定状态,以及它需要多长时间。

或者,您可以使用更复杂的对象作为值,并为原始时间戳记录失败者的返回代码(在这种情况下,您拥有的信息比“返回”更完整)。