C#线程处理机制

问题描述:

比方说,我有一个暴露的接口,例如:C#线程处理机制

interface IMyService 
{ 
    MyResult MyOperation(); 
} 

此操作是同步的,并返回一个值。

我实现接口具有执行以下操作:

  • 呼叫异步方法
  • 等待事件#1
  • 等待事件#2

这是由于一个与我合作的第三方COM对象。

此代码类似于以下

public MyResult MyOperation() 
{ 
    _myCOMObject.AsyncOperation(); 

    //Here I need to wait for both events to fire before returning 
} 

private void MyEvent1() 
{ 
    //My Event 1 is fired in this handler 
} 

private void MyEvent2() 
{ 
    //My Event 2 is fired in this handler 
} 

我的两个事件可以顺序发生,这是很随机的。

我可以使用什么正确的线程机制来同步它?在我必须开始等待第二个事件之前,我使用了ManualResetEvent,并且没有看到用于这两个事件的简单方法。这两个事件设置了变量,使我可以为MyOperation()创建返回值。

关于良好实施的任何想法?我无法控制第三方对象的实现方式。

两个ManualResetEvent s应该为你做的伎俩。在致电_myCOMObject.AsyncOperation()之前,只需将它们初始化为假。就像这样:

private ManualResetEvent event1; 
private ManualResetEvent event2; 

public MyResult MyOperation() 
{ 
    event1 = new ManualResetEvent(false); 
    event2 = new ManualResetEvent(false); 

    _myCOMObject.AsyncOperation(); 

    WaitHandle.WaitAll(new WaitHandle[] { event1, event2 }); 
} 

private void MyEvent1() 
{ 
    event1.Set(); 
} 

private void MyEvent2() 
{ 
    event2.Set(); 
} 

编辑

感谢您的意见。我改变了等待电话使用WaitAll

+0

这是有道理的。我的困惑是在多个ManualResetEvents的Reset()上调用哪一个,并且我还必须将整个调用锁定到MyOperation(),以便两个线程不能同时调用该函数。 – jonathanpeppers 2009-08-11 16:29:25

+2

尽管这是一个非常好的解决方案,但我会使用WaitAll(如下所示)而不是两个WaitOne阻塞调用,WaitAll为系统提供了有关阻塞的更多上下文,并有可能为更好的调度提供机会。 – meandmycode 2009-08-11 16:31:32

+0

感谢您的反馈。我已经更新了我的答案。 – 2009-08-11 17:56:20

我不知道我理解你的问题,但AutoResetEvent.WaitAll似乎解决了你的问题,如果我说得对。它允许您设置多个处理程序,并且只有在全部设置后才会释放。

http://msdn.microsoft.com/en-us/library/z6w25xa6.aspx

我实现的例子如下:

namespace ConsoleApplication1 
{ 

    class Program 
    { 
     private static WaitHandle[] waitHandles; 
     private static event EventHandler Evt1; 
     private static event EventHandler Evt2; 

     static void Main(string[] args) 
     { 
      waitHandles = new WaitHandle[]{ 
       new ManualResetEvent(false), 
       new ManualResetEvent(false) 
      }; 

      Evt1 += new EventHandler(Program_Evt1); 
      Evt2 += new EventHandler(Program_Evt2); 

      OnEvt1(); 
      OnEvt2(); 

      WaitHandle.WaitAll(waitHandles); 

      Console.WriteLine("Finished"); 
      Console.ReadLine(); 
     } 

     static void Program_Evt2(object sender, EventArgs e) 
     { 
      Thread.Sleep(2000); 
      ((ManualResetEvent)waitHandles[0]).Set(); 
     } 

     static void Program_Evt1(object sender, EventArgs e) 
     { 
      ((ManualResetEvent)waitHandles[1]).Set(); 
     } 

     static void OnEvt1() 
     { 
      if (Evt1 != null) 
       Evt1(null, EventArgs.Empty); 
     } 

     static void OnEvt2() 
     { 
      if (Evt2 != null) 
       Evt2(null, EventArgs.Empty); 
     } 


    } 
} 

我让它睡在这个例子中和了WaitAll功能

干杯的目的,

安德鲁

PS另一个例子是使用AsyncCallback,这个例子非常快速而且很脏,但是给你更多的钥匙来打开:-)。希望这可以帮助!!

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     private static WaitHandle[] waitHandles; 
     private static event EventHandler Evt1; 
     private static event EventHandler Evt2; 

     static void Main(string[] args) 
     { 
      waitHandles = new WaitHandle[]{ 
       new ManualResetEvent(false), 
       new ManualResetEvent(false) 
      }; 

      var callabck1 = new AsyncCallback(OnEvt1); 
      var callabck2 = new AsyncCallback(OnEvt2); 

      callabck1.Invoke(new ManualResetResult(null, (ManualResetEvent)waitHandles[0])); 
      callabck2.Invoke(new ManualResetResult(null, (ManualResetEvent)waitHandles[1])); 

      WaitHandle.WaitAll(waitHandles); 

      Console.WriteLine("Finished"); 
      Console.ReadLine(); 

     } 

     static void OnEvt1(IAsyncResult result) 
     { 
      Console.WriteLine("Setting1"); 
      var handle = result.AsyncWaitHandle; 
      ((ManualResetEvent)handle).Set(); 
     } 

     static void OnEvt2(IAsyncResult result) 
     { 
      Thread.Sleep(2000); 
      Console.WriteLine("Setting2"); 
      var handle = result.AsyncWaitHandle; 
      ((ManualResetEvent)handle).Set(); 
     } 

    } 

    public class ManualResetResult : IAsyncResult 
    { 
     private object _state; 
     private ManualResetEvent _handle; 

     public ManualResetResult(object state, ManualResetEvent handle) 
     { 
      _state = state; 
      _handle = handle; 
     } 

     #region IAsyncResult Members 

     public object AsyncState 
     { 
      get { return _state; } 
     } 

     public WaitHandle AsyncWaitHandle 
     { 
      get { return _handle; } 
     } 

     public bool CompletedSynchronously 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public bool IsCompleted 
     { 
      get { throw new NotImplementedException(); } 
     } 

     #endregion 
    } 
}