• 线程 ManualResetEvent 类


     Reset(): 当一个线程开始一个活动(此活动必须完成后,其他线程才能开始)时, 它调用 Reset 以将 ManualResetEvent 置于非终止状态。此线程可被视为控制 ManualResetEvent。

    为了把状态修改为无信号的,必须调用ReSet()方法。

    WaitOne(): 调用ManualResetEvent 上的 WaitOne 的线程将阻止,并等待信号。    

    Set ()当控制线程完成活动时,它调用 Set 以发出等待线程可以继续进行的信号。并释放所有等待线程。Set将事件状态设置为终止状态,允许一个或多个等待线程继续。

    为了把状态修改为有信号的,必须调用Set()方法。

    ManualResetEvent对象只能拥有两种状态之一:有信号(True)或无信号(false)。ManualResetEvent类继承于WaitHandle类,其构造函数的参数可确定对象的初始状态。

    Set()和Reset()方法返回一个布尔值,表示是否进行了成功的修改。

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    namespace ManualResetshiyan
    {
        class Program
        {
            static void Main(string[] args)
            {
                ManualResetEvent mansig;
                mansig = new ManualResetEvent(false);
                Console.WriteLine("ManualResetEvent Before WaitOne");
                bool b = mansig.WaitOne(1000, true);
                Console.WriteLine("ManualResetEvent After WaitOne" + b);
                Console.ReadLine();
            }
        }
    }
     

    上面的例子中,构造了false值的ManualResetEvent对象,布尔值False把ManualResetEvent对象的初始状态设置为无信号。接着调用基类WaigHandle的WaitOne()方法。程序块在WaitOne()方法中暂停一秒,然后因为超时而退出。ManualResetEvent的状态仍然是False,因而WaitOne()返回的布尔值b是False。

    下面的例子把有信号改为无信号,调用ReSet()方法,Set()方法。

    [csharp] view plaincopy
     
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Text;  
    4. using System.Threading;  
    5. namespace 同步  
    6. {  
    7.     class Program  
    8.     {  
    9.         static void Main(string[] args)  
    10.         {  
    11.   
    12.             ManualResetEvent mansig;  
    13.             mansig = new ManualResetEvent(true);  
    14.   
    15.             bool state = mansig.WaitOne(9000, true);  
    16.             Console.WriteLine("ManualResetEvent After WaitOne" + state);  
    17.           
    18.             mansig.Reset();  
    19.             state = mansig.WaitOne(9000, true);  
    20.             Console.WriteLine("ManualResetEvent After WaitOne" + state);  
    21.        
    22.             mansig.Set();  
    23.             state = mansig.WaitOne(9000, true);  
    24.             Console.WriteLine("ManualResetEvent After WaitOne" + state);  
    25.         }  
    26.     }  
    27. }   


     在ManualReset中,MnualTResetEvent对象的构造函数将其状态设置为有信号(true),结果,线程不在第一个

    WaitOne()方法中等待,并返回True值。接着,ManualResetEvent对象的状态重新设置为无信号的(false),于是线程在超时之前必须等待5秒,调用Set()方法后也不用等待。

    下面在看一个程序:

    [csharp] view plaincopy
     
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Text;  
    4. using System.Threading;  
    5. namespace 同步实验  
    6. {  
    7.     class Program  
    8.     {    ///   
    9.         /// ManualResetEvent建立时是把false作为start的初始状态,这个类用于通知另一个线程,让它等待一个或多个线程。  
    10.         /// 如这个例子中,等待线程thread1线程调用mre.WaitOne(), 用于发信号的线程调用mre.Set().  
    11.         ///   
    12.         public static ManualResetEvent mre = new ManualResetEvent(false);  
    13.         public static void trmain()  
    14.         {  
    15.   
    16.             Thread tr = Thread.CurrentThread;  
    17.   
    18.             Console.WriteLine(tr.Name + " 开始第一波等待");  
    19.             mre.WaitOne();   //等到什么时候呢?等到mre.Set()被调用  
    20.             Console.WriteLine(tr.Name + " 第一波启动t");  
    21.   
    22.             mre.Reset();   //再次重置  
    23.             Console.WriteLine(tr.Name + " 开始第二波等待");  
    24.             mre.WaitOne();   //再次等待  
    25.             Console.WriteLine(tr.Name + " 第二波启动");  
    26.   
    27.             for (int x = 0; x < 10; x++)  
    28.             {  
    29.   
    30.                 Thread.Sleep(1000);  
    31.                 Console.WriteLine(tr.Name + ": " + x);  
    32.             }  
    33.         }    
    34.   
    35.   
    36.         static void Main(string[] args)  
    37.         {  
    38.             Thread thrd1 = new Thread(new ThreadStart(trmain));  
    39.             thrd1.Name = "thread1";  
    40.             thrd1.Start();  
    41.   
    42.             Thread thrd2 = new Thread(new ThreadStart(trmain));  
    43.             thrd2.Name = "thread2";  
    44.             thrd2.Start();  
    45.   
    46.             for (int x = 0; x < 10; x++)  
    47.             {  
    48.                 Thread.Sleep(900);  
    49.                 Console.WriteLine("Main :" + x);  
    50.                 if (5 == x)  
    51.                 {  
    52.                     mre.Set();   //子线程的mre.WaitOne()可以执行了。第一次等待进程  
    53.                     //;   //如果什么都不做呢,mre.Wait()那个线程就一直等在那里了?  
    54.                 }  
    55.             }  
    56.             while (thrd1.IsAlive)  
    57.             {  
    58.   
    59.                 Thread.Sleep(1000);  
    60.   
    61.                 Console.WriteLine("Main: waiting for thread to stop...");  
    62.                 mre.Set();   //第二次通知等待进程  
    63.             }  
    64.         }  
    65.     }  
    66.     
    67. }  

    下面在看一个关于ManualResetEvent waitany的程序:

    waitany一直等到有信号 才开始执行下面的语句.

    [csharp] view plaincopy
     
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Text;  
    4. using System.Threading;  
    5. namespace 同步实验  
    6. {  
    7.     class Program  
    8.     {  
    9.         public static ManualResetEvent m_eventTemporaryTrigger;  
    10.         public static ManualResetEvent m_eventQuitTemporary;  
    11.   
    12.         private static string m_triggerParam;  
    13.   
    14.         public static void TemporaryConnThreadTrigger(String param)  
    15.         {  
    16.             m_triggerParam = param;  
    17.             m_eventTemporaryTrigger.Set();  
    18.         }  
    19.   
    20.         static void Main(string[] args)  
    21.         {  
    22.             m_eventTemporaryTrigger =new ManualResetEvent(true);  
    23.             m_eventQuitTemporary = new ManualResetEvent(true);  
    24.             //m_eventQuitTemporary = new ManualResetEvent(false);  
    25.             m_eventTemporaryTrigger.Reset(); //临时线程处于工作之中时,m_eventTemporaryTrigger始终处于被触发状态  
    26.           //  Trigger.strmain();  
    27.             WaitHandle[] events = new WaitHandle[2];  
    28.             events[0] = m_eventQuitTemporary;  
    29.             events[1] = m_eventTemporaryTrigger;  
    30.             //等待退出信号事件或触发事件  
    31.             // 返回结果:  
    32.             //     满足等待的对象的数组索引。  
    33.             int index = WaitHandle.WaitAny(events);  
    34.             Console.WriteLine("run no wait");  
    35.             if (index == 0)  
    36.             {//如果是将Main(),第三行置为false则不执行下面语句  
    37.                 Console.WriteLine("m_eventQuitTemporary run");  
    38.                 Console.WriteLine(m_triggerParam);  
    39.             }  
    40.         }  
    41.    }  
    42.     public class Trigger   
    43.     {  
    44.       public static void strmain()  
    45.       {  
    46.           Program.TemporaryConnThreadTrigger("m_eventQuitTemporary run show");  
    47.       }  
    48.     }  
    49. }  

    要注意的是ManualResetEvent和AutoResetEvent 的构造函数都有一个bool的参数,用这个参数可以指定初始情况下,同步对象的处于阻塞(设置为false)还是非阻塞(设置为true)的状态。 
    另外WaitOne方法也可以带两个参数: 
    WaitOne (int millisecondsTimeout,bool exitContext) 
    millisecondsTimeout:等待的毫秒数,或为 Timeout.Infinite (-1),表示无限期等待。 
    exitContext:为 true,则等待之前先退出上下文的同步域(如果在同步上下文中),然后在稍后重新获取它;否则为false。 
    就是说,等待是可以加上一个期限的,如果等待的同步对象一直都不Set()的话,那么程序就会卡死,所以在WaitOne方法里面可以放置一个时间期限,单位是毫秒。

  • 相关阅读:
    tomcat 启动超时
    读书笔记-String
    读书笔记-集合
    读书笔记-算法
    多变量梯度下降
    多变量线性回归
    梯度下降算法在线性回归中的运用
    梯度下降
    线性回归——代价函数
    线性回归
  • 原文地址:https://www.cnblogs.com/bdbw2012/p/3898823.html
Copyright © 2020-2023  润新知