C#线程机制

时间:2009-08-11 16:15:47

标签: c# multithreading asynchronous thread-safety

假设我有一个暴露的界面:

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()创建返回值。

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

3 个答案:

答案 0 :(得分:4)

两个ManualResetEvent应该为你做的伎俩。在调用_myCOMObject.AsyncOperation()之前,只需将它们初始化为false即可。像这样:

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

答案 1 :(得分:2)

我的实现示例如下:

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功能

,我让它休眠

干杯,

安德鲁

P.S。另一个例子是使用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
    }
}

答案 2 :(得分:0)

我不确定我理解你的问题,但是如果我做对了,AutoResetEvent.WaitAll似乎可以解决你的问题。它允许您设置多个处理程序,只有在设置了所有处理程序后才会释放它。

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