异步调用新手问题

时间:2009-03-20 17:30:53

标签: c# asynchronous

我正在开发一个小项目,我需要一个接一个地进行两次异步调用。

我的代码看起来像这样:

AsynchronousCall1();
AsynchronousCall2();

我遇到的问题是两个调用都需要一到两秒的时间来执行,我永远不知道哪一个会完成最后一个。我正在寻找的是一种确定谁最后完成的方法。如果Call1()最后完成,我会做一件事。如果Call2()最后完成,我会做另一件事。

4 个答案:

答案 0 :(得分:6)

这是使用lock确保只有一个线程可以输入一段代码的简单示例。但这是一个通用的例子,可能是也可能不是最适合您的应用程序。在您的问题中添加一些细节,以帮助我们找到您要查找的内容。

 void AsynchronousCall1()
 {
      // do some work
      Done("1");
 }

 void AsynchronousCall2()
 {
      // do some work
      Done("2");
 }

 readonly object _exclusiveAccess = new object();
 volatile bool _alreadyDone = false;
 void Done(string who)
 {
      lock (_exclusiveAccess)
      {
           if (_alreadyDone)
               return;

           _alreadyDone = true;
           Console.WriteLine(who + " was here first");
      }
  }

答案 1 :(得分:2)

我相信有一个方法是Thread类的成员,用于检查特定线程并确定其状态。另一种选择是使用BackgroundWorker,因为这样可以通过创建单独的方法来说明完成该线程时会发生什么。

“thread-unsafe”选项是使用类变量,并且在每个线程的末尾如果它没有被锁定/已经有另一个线程的值,则不要设置它。否则设置它。

然后在你的main方法中,在调用等待所有线程完成之后,测试类变量。

这将为您提供关于首先完成哪个主题的答案。

答案 2 :(得分:1)

您可以使用两个ManualResetEvent对象执行此操作。我们的想法是让主线程初始化为无信号,然后调用异步方法。然后主线程在两个对象上执行WaitAny。当AsynchronousCall1完成时,它会发出一个对象的信号。当AsynchronousCall2完成时,它会发出另一个信号。这是代码:

ManualResetEvent Event1 = new ManualResetEvent(false);
ManualResetEvent Event2 = new ManualResetEvent(false);

void SomeMethod()
{
    WaitHandle[] handles = {Event1, Event2};
    AsynchronousCall1();
    AsynchronousCall2();
    int index = WaitHandle.WaitAny(handles);
    // if index == 0, then Event1 was signaled.
    // if index == 1, then Event2 was signaled.
}

void AsyncProc1()
{
    // does its thing and then
    Event1.Signal();
}

void AsyncProc2()
{
    // does its thing and then
    Event2.Signal();
}

这里有几点需要注意。如果两个异步方法在调用WaitAny之前完成,则无法说明哪个完成了。此外,如果两个方法彼此非常接近(即,调用1完成,则在主线程的等待被释放之前调用2完成),则无法确定哪个方法首先完成。

答案 3 :(得分:0)

您可能想要查看Blackboard设计模式:http://chat.carleton.ca/~narthorn/project/patterns/BlackboardPattern-display.html。该模式设置了一个公共数据存储,然后让代理(彼此一无所知 - 在这种情况下,您的异步调用)在该公共位置报告其结果。然后,你的黑板'主管'会知道哪个通话先完成,并可以相应地指导你的程序。