我有一个桌面应用程序(.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#?
答案 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里面查看哪一个仍处于待定状态,以及它需要多长时间。
或者,您可以使用更复杂的对象作为值,并为原始时间戳记录失败者的返回代码(在这种情况下,您拥有的信息比“返回”更完整)。