c# - 等待带有回调的多个方法完成

标签 c# multithreading asynchronous .net-2.0

我有多个异步方法需要调用并等待它们全部完成。异步方法都具有在异步处理完成时执行的回调参数。所以我想我需要在每个回调中放置一些信号设备,然后在继续之前等待所有信号到来。

在进行一些搜索后,我想我可以使用一组 AutoResetEvents,然后调用 WaitHandle.WaitAll 来等待它们。像这样的东西:

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

我想知道这是否是一个好方法,或者是否有更好/更简单的方法。我需要一个适用于 .Net 2.0 的解决方案,但我也想知道哪些其他解决方案可用于更高版本的 .Net。

编辑: 尝试此代码后,我发现它不起作用。 UI 线程停止在 WaitHandles.WaitAll(waitHandles) 并且回调永远不会运行...

在 DoWork 方法中,有代码在后台线程上异步运行,然后我尝试从该后台线程通过在 UI 线程的控件上调用的 BeginInvoke 运行回调。但是,回调永远不会在 UI 线程上执行。知道我做错了什么吗?

编辑 2: 我意识到它为什么不起作用 - 调用 WaitHandles.WaitAll(waitHandles) 的线程是回调试图在其上运行的线程(UI 线程)。所以当然,如果线程正在等待信号,回调将永远不会在同一个线程上运行,因此永远不会调用 Set()。 WaitAll(waitHandles) 和 Set() 应该可以工作,只要它们不打算在同一线程上运行。我想我需要修复它,以便在 UI 线程等待时回调在后台线程上运行。如果我的想法不正确,请告诉我。

最佳答案

是的,使用事件是等待多个回调完成的合理方式,对于 2.0,如果您不能使用外部库,这可能是您可以做的最好的事情。

你可以用一个事件重写代码并计算回调完成,但它可能更复杂(同时允许无限数量的回调)。或者可以通过 Semaphore 实现类似的方法.

如果您可以使用 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;

关于c# - 等待带有回调的多个方法完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32321851/

相关文章:

c# - 在 ASP.NET Web API 中返回错误的最佳实践

c# - 使 WinForms UserControl 出现在 WPF Visual C# 项目的工具箱中?

c# - 无法将源类型 'string' 转换为目标类型 'uint' c# 中的错误

multithreading - 我们可以在单线程程序中使用竞争条件吗?

javascript - 如何在函数内等待事件监听器?

c# - C# 中类型安全的即发即弃异步委托(delegate)调用

c# - 覆盖 WCF 服务中的 ToString 方法

python多进程启动失败

java - 将 : Spilitting compound, 非原子操作锁定为更简单的原子操作

Javascript:如何实现异步函数队列(无需库)