ManualResetEvent和AutoResetEvent的区别

在讨论这个问题之前,我们先了解这样一种观点,线程之间的通信是通过发信号来进行沟通的。(这不是废话)

 

      先来讨论ManualResetEvent,讨论过程中我会穿插一些AutoResetEvent的内容,来做对比:

      ManualResetEvent都可以阻塞一个或多个线程,直到收到一个信号告诉ManualResetEvent不要再阻塞当前的线程。

可以想象ManualResetEvent这个对象内部有一个Boolean类型的属性IsRelease来控制是否要阻塞当前线程。这个属性我们在初始化的时候可以设置它,如ManualResetEvent event=new ManualResetEvent(false);这就表明默认的属性是要阻塞当前线程。

      代码举例:

        ManualResetEvent _manualResetEvent = new ManualResetEvent(false);

        private void BT_Temp_Click(object sender, RoutedEventArgs e) 
        { 
            Thread t1 = new Thread(this.Thread1Foo); 
            t1.Start(); //启动线程1
            Thread t2 = new Thread(this.Thread2Foo); 
            t2.Start(); //启动线程2
            Thread.Sleep(3000); //睡眠当前主线程,即调用BT_Temp_Click的线程
            _manualResetEvent .Set();   //想象成将IsRelease设为True 
        }

        void Thread1Foo() 
        { 
            _manualResetEvent .WaitOne(); 

//阻塞线程1,直到主线程发信号给线程1,告知_menuResetEvent你的IsRelease属性已经为true,

//这时不再阻塞线程1,程序继续往下跑

            MessageBox.Show("t1 end"); 
        }

        void Thread2Foo() 
        { 
            _manualResetEvent .WaitOne();

//阻塞线程2,直到主线程发信号给线程1,告知_menuResetEvent你的IsRelease属性已经为true,

//这时不再阻塞线程2,程序继续往下跑

            MessageBox.Show("t2 end"); 
        }


 

 

       注意这里ManualResetEvent和AutoResetEvent的一个重要区别:

       manual的话肯定会给线程1和线程2都发送一个信号,而auto只会随机给其中一个发送信号。

 

 

       为什么一个叫manual而一个叫auto呢?我想这是很多人的疑问,现在我们就来看这个问题。

       刚才_manualResetEvent .Set();的这句话我想大家都明白了,可以看做将IsRelease的属性设置为true.线程1中

 _manualResetEvent.WaitOne();接收到信号后不再阻塞线程1。在此之后的整个过程中IsRelease的值都是true.如果

想将IsRelease的值回复成false,就必须再调用_manualResetEvent.Reset()的方法。

 

       如果是_autoResetEvent.set(),那么_autoResetEvent.WaitOne()后会自动将IsRelease的值自动设置为false.

这就是为什么一个叫auto,一个叫manual.

AutoResetEventManualResetEvent的一个现象和问题

10-18

两种情形:rn1)rn public static [b]AutoResetEvent[/b] acceptDone = new [b]AutoResetEvent[/b](false);rnrn ...rn Listen_BeginAccept();rn ...rnrnrnrn public void AcceptCallback(IAsyncResult ar)rn rn Socket listen = (Socket)ar.AsyncState;rn handler = listen.EndAccept(ar);rnrn acceptDone.Set();rnrn Listen_BeginAccept();rn rnrn private void Listen_BeginAccept()rn rn //listen is the server socket to listen on the portrn listen.BeginAccept(new AsyncCallback(AcceptCallback), listen);rn Console.WriteLine("Enter BeginAccept WaitOne");rnrn acceptDone.WaitOne();rn rnrn2)rn public static [b]ManualResetEvent[/b] acceptDone = new [b]ManualResetEvent[/b](false);rnrn Listen_BeginAccept();rnrn public void AcceptCallback(IAsyncResult ar)rn rn Socket listen = (Socket)ar.AsyncState;rn handler = listen.EndAccept(ar);rnrn acceptDone.Set();rn //[color=#FF0000]Thread.Sleep(100);[/color]rn Listen_BeginAccept();rn rnrn private void Listen_BeginAccept()rn rn [b]acceptDone.Reset();[/b]rnrn //listen is the server socket to listen on the portrn listen.BeginAccept(new AsyncCallback(AcceptCallback), listen);rn Console.WriteLine("Enter BeginAccept WaitOne");rnrn acceptDone.WaitOne();rn rn rnrn两种方案,在1)中执行是没有问题的,但是在2)中问题就出现了。rn在2)中,acceptDone.Set();之后,程序会直接跑到函数Listen_BeginAccept()里面,而不是先通过WaitOne,从而会一直wait从而不能继续执行,除非我加一句红色的Thread.Sleep(100),(其实这儿需要的是一个很短的时间,不一定非要sleep,一句Consolo.WriteLine()也行),这样才能正确执行。rn那为什么1)中可以先通过WaitOne执行,而不是先进入函数Listen_BeginAccept()?rnrn原因是什么?rn 论坛

关于ManualResetEvent 阻止线程

12-25

[code=csharp] ManualResetEvent resumeEvent = new ManualResetEvent(false);rn volatile bool paused;rn /// rn /// 阻止线程rn /// rn void pause()rn rn resumeEvent.Reset();rn paused = true;rn rn /// rn /// 继续线程rn /// rn void Resume()rn rn paused = false;rn resumeEvent.Set();rn rn public void MendthCall(string[] args, int index)rn rn string str1 = "";rn //获取服务器配置信息rn List list = GetSeverConfig();rn //服务器调用方法rn RemotingServerConn conn = new RemotingServerConn();rnrnrn for (int i = 0; i < list.Count; i++)rn rn rn //连接服务器rn ExecuteCOM ec = conn.ServerConn(list[i]);rn str1 = IsLeisureServer(ec);//查找到空闲状态任务的句柄rn if (str1 != null && str1.Trim() != "")rn rn break;rn rn rn if (str1 == "")rn rn rn resumeEvent.WaitOne();rn //pause();rn rn tryrn rn for (int i = 0; i < list.Count; i++)rn rn //连接服务器rn ExecuteCOM ec = conn.ServerConn(list[i]);rn string str = IsLeisureServer(ec);//查找到空闲状态任务的句柄rn if (str != null && str.Trim() != "")rn rn _ICOMcallback = new ICOMCallBack();rn _ICOMcallback.OnExecuteComplete_Event += new ExecuteComplete_Event(ExecuteComplete_EventMethod);rn ec.AddOnlineCallBack(_ICOMcallback);rn if (index != -1)rn rn args[index] = str;rn rn ec.ExecuteAsyncPreAndCal(args, index);rn break;rn rn rn rn catch (Exception ex)rn rn MessageBox.Show(ex.ToString(), "错误提示");rn rn rn /// rn /// 获取返回结果rn /// rn /// rn void ExecuteComplete_EventMethod(string str)rn rn if (EventRemotingArgs != null)rn rn //if (paused)rn //rn //Resume();rn resumeEvent.Set();rn resumeEvent.Reset();rn //rn RemotingResult result = new RemotingResult();rn result.result = str;rn EventRemotingArgs(this, result);rn rn[/code]rn我想在接收事件哪里给ManualResetEvent set() 但是set执行完了,阻止的线程并没有执行、我这么写就没问题,下面这个例子没问题,但是上面这个例子就是执行了set() 但是WaitOne()阻止在哪的线程缺没动静。- -rnrn[code=csharp] bool bol = false;rn ManualResetEvent manual = new ManualResetEvent(false);rn private void button1_Click(object sender, EventArgs e)rn rn Thread th = new Thread(new ThreadStart(ss));rn th.Start();rn rn textBox1.Text += "qwe";rn rn rnrn void ss()rn rn //Thread.Sleep(3000);rn this.Invoke(new MethodInvoker(delegate() textBox1.Text += "123243"; ));rn manual.WaitOne();rn Thread.Sleep(3000);rn this.Invoke(new MethodInvoker(delegate() textBox1.Text += "456"; )); rn rnrn private void button2_Click(object sender, EventArgs e)rn rn manual.Set();rn manual.Reset();rn rn rn[/code] 论坛

没有更多推荐了,返回首页