简体   繁体   English

等待带有回调的多种方法完成

[英]Wait for multiple methods with callbacks to finish

I have multiple asynchronous methods that I need to call and wait for them all to finish. 我有多个异步方法需要调用,并等待它们全部完成。 The asynchronous methods all have callback parameters that execute when the asynchronous processing has finished. 异步方法都具有在异步处理完成后执行的回调参数。 So I'm thinking that I need to put some signalling device in each callback and then wait for all the signals to come before continuing. 所以我在想,我需要在每个回调中放置一些信号设备,然后等待所有信号出现,然后再继续。

After doing some searching I'm thinking I could use a an array of AutoResetEvents and then call WaitHandle.WaitAll to wait for them. 经过一些搜索之后,我想我可以使用一个AutoResetEvents数组,然后调用WaitHandle.WaitAll等待它们。 Something like: 就像是:

WaitHandle[] waitHandles = new WaitHandle[] 
{
    new AutoResetEvent(false),
    new AutoResetEvent(false)
};

DoWorkA((callback) =>
{
    waitHandles[0].Set();
});

DoWorkB((callback) =>
{
    waitHandles[1].Set();
});

// wait for DoWorkA and DoWorkB to finish
WaitHandles.WaitAll(waitHandles);

// continue with the processing

I'd like to know if this is a good way to do it, or if there is a better/simpler method. 我想知道这是否是一个好方法,或者是否有更好/更简单的方法。 I need an solution for .Net 2.0, but I'd also be interested to know what other solutions would be available with a later version of .Net. 我需要一个适用于.Net 2.0的解决方案,但我也想知道更高版本的.Net将提供哪些其他解决方案。

EDIT: After trying this code I found it doesn't work. 编辑:尝试此代码后,我发现它不起作用。 The UI thread stops at WaitHandles.WaitAll(waitHandles) and the callbacks never run... UI线程在WaitHandles.WaitAll(waitHandles)处停止,并且回调永远不会运行...

Inside the DoWork methods there is code being run asnychronously on a background thread, and then from that background thread I attempt to run the callback through BeginInvoke called on a control from the UI thread. 在DoWork方法内部,有代码在后台线程上异步运行,然后从该后台线程我尝试通过UI线程在控件上调用的BeginInvoke运行回调。 However, the callback never gets executed on the UI thread. 但是,回调永远不会在UI线程上执行。 Any ideas what I'm doing wrong? 有什么想法我做错了吗?

EDIT 2: I realized why it doesn't work - the thread calling WaitHandles.WaitAll(waitHandles) is the same thread that the callbacks are attempting to run on (the UI thread). 编辑2:我意识到了为什么它不起作用-调用WaitHandles.WaitAll(waitHandles)的线程与回调试图在其上运行的线程相同(UI线程)。 So of course if the thread is waiting for the signal, the callbacks will never run on that same thread and so Set() will never be called. 因此,当然,如果线程正在等待信号,则回调将永远不会在同一线程上运行,因此Set()将永远不会被调用。 The WaitAll(waitHandles) and Set() should work, as long as they are not inteded to be run on the same thread. 只要不打算在同一线程上运行,WaitAll(waitHandles)和Set()应该可以工作。 I think I need to fix it so that the callbacks run on a background thread while the UI thread waits. 我认为我需要对其进行修复,以使回调在UI线程等待时在后台线程上运行。 Please let me know if my thinking here is incorrect. 如果我的想法不正确,请告诉我。

Yes using events is reasonable way to wait for multiple callback completion and for 2.0 it is probably the best you can do if you can't use external libraries. 是的,使用事件是等待多个回调完成的合理方法,对于2.0,如果您不能使用外部库,则可能是最好的选择。

You may rewrite code with one event and counting callback completion, but it may be more complicated (also allow unlimited number of callbacks at the same time). 您可以使用一个事件重写代码并计算回调完成的次数,但可能会更复杂(同时允许无限数量的回调)。 Or similar approach may be implemented via Semaphore . 或可以通过信号量实现类似的方法。

If you can use 4.5+ than rewriting methods with async / await may be better option. 如果您可以使用4.5+,那么用async / await重写方法可能是更好的选择。

  // use "async Task(...)" as equivalent of "void DoWorkA(...)".
  async Task<int> DoWorkAAsync(int arg1)
  {
     var serviceResult = await service.CallAsync(arg1);
     return ParseServiceResult(serviceResult);
  }

  async Task<int> DoWorkBAsync() 
  { 
     ... await SomeAsync(1,2,3);...
     return someResult;
  }

  var tasks = new[] {DoWorkAAsync(42), DoWorkBAsync() }; 
  await Task.WhenAll(tasks);

  var resultOfA = tasks[0].Result;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM