精华内容
下载资源
问答
  • C# 线程通信

    2016-08-04 17:06:00
    C#线程通信 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 using System.Threading.Tasks; 7 8 namespace ...

    C#多线程通信

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading;
     6 using System.Threading.Tasks;
     7 
     8 namespace App.Test.Csharep.线程通信
     9 {
    10     public class MainThread
    11     {
    12         /// <summary>
    13         /// 开始执行通知
    14         /// </summary>
    15         private EventWaitHandle dataChangeEvent = new AutoResetEvent(false);
    16         
    17 
    18         public int openDoorNum = 0;
    19 
    20         /// <summary>
    21         /// 测试流程: 完成10次开门后,每次开门完成都要完成进门操作,主线程完成开门,子线程完成进门
    22         /// </summary>
    23         public void Run()
    24         {
    25             var thread = new Thread(new ThreadStart(InputDoor));
    26             thread.Name = "进门线程";
    27             thread.IsBackground = true;
    28             thread.Start();
    29 
    30             Thread.Sleep(500);
    31 
    32             for (int i = 0; i < 10; i++)
    33             {
    34                 openDoorNum++;
    35                 Console.WriteLine("AA完成开门第" + openDoorNum + "次开门");
    36 
    37                 /// 通知已经完成开门操作
    38                 dataChangeEvent.Set();
    39 
    40                 /// 在执行dataChangeEvent.Set()后,dataChangeEvent.WaitOne()开始获取信号,为防止没有获取到信号时
    41                 /// 又执行dataChangeEvent.Set()方法,则上次的dataChangeEvent.WaitOne()需要执行的代码不会被执行,
    42                 /// 所以暂时休眠,否则进门可能次数不够
    43                 Thread.Sleep(1);
    44             }
    45 
    46             Console.Read();
    47         }
    48 
    49         /// <summary>
    50         /// 完成进门操作
    51         /// </summary>
    52         private void InputDoor()
    53         {
    54             ///收到开门的线程通知,WaitOne方法如果在通知线程set()前如果能及时收到信号,则一直会处于阻塞代码
    55             /// 如果在dataChangeEvent.WaitOne()过程中获取信号同时,被调用线程给set()了,则dataChangeEvent.WaitOne()
    56             /// 应该是收不到信号的,所以要在调用线程中执行完dataChangeEvent.set()后应该休眠一会,在调用dataChangeEvent.set()
    57 
    58             /// 保证子线程一直在处于运行状态
    59             while (true)
    60             {
    61                 //if (dataChangeEvent.WaitOne())
    62                 //{
    63                 //    Console.WriteLine("\tA第" + openDoorNum + "次进门");
    64                 //}
    65 
    66                 /// 等待100毫秒,没有收到信号则释放,继续往下面执行,date会被赋值
    67                 if (dataChangeEvent.WaitOne(100, false))
    68                 {
    69                     Console.WriteLine("\t 【" + Thread.CurrentThread.Name + "】A第" + openDoorNum + "次进门");
    70                 }
    71             }
    72         }
    73     }
    74 }

     

    转载于:https://www.cnblogs.com/yitong/p/ManualResetEvent_AutoResetEvent.html

    展开全文
  • 通常,AutoResetEvent用于通知正在等待线程已发生事件,允许线程通过发信号互相通信。 AutoResetEvent时间对象提供了给我们可以控制线程执行的先后顺序,他的常用方法: Set设置并发送信号 Reset重置信号,也就是...

    线程的通知机制

    AutoResetEvent是线程实现通知操作的重要方法。通常,AutoResetEvent用于通知正在等待线程已发生事件,允许线程通过发信号互相通信。

    AutoResetEvent时间对象提供了给我们可以控制线程执行的先后顺序,他的常用方法:

    Set设置并发送信号

    Reset重置信号,也就是使信号无效

    WaitOne等待一个信号

    WaitAny静态方法,等待一个信号数组,信号数组里面有任何信号都可以,否则等待

    WaitAll静态方法,等待一个i额信号数组,信号数组里面的信号全部到齐才可以,否则等待

     

    创建一个AutoResetEvent对象,构造方法里面需要带一个bool类型的参数,

    AutoResetEvent myResetEvent = new AutoResetEvent(false);

    这个参数如果是false表示时间开始是无信号状态的,当参数为true表示创建的时间开始是有信号的,就相当于使用false参数创建时间后立即设定了Set方法。

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    namespace AutoResetEventTest
    {
        class Program
        {
            static AutoResetEvent myResetEvent = new AutoResetEvent(false);
            static int number;
            static void Main(string[] args)
            {
                Thread t = Thread.CurrentThread;
                t.Name = "写线程";
    
                Thread myReaderThread = new Thread(MyReadThreadProc);
                myReaderThread.Name = "读线程";
                myReaderThread.Start();
    
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("{0}写的值是{1}", t.Name, i);
                    number = i;
                    myResetEvent.Set();
                    Thread.Sleep(1);
                }
    
                myReaderThread.Abort();
            }
    
            static void MyReadThreadProc()
            {
                while (true)
                {
                    myResetEvent.WaitOne();
                    Console.WriteLine("{0}读到的值是{1}", Thread.CurrentThread.Name, number);
                }
            }
        }
    }
    复制代码

    例程2

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    namespace AutoResetEventTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                Person p = new Person();
                Thread th1 = new Thread(p.GetCar);
                th1.Start();
                Thread th2 = new Thread(p.GetHome);
                th2.Start();
                Thread th3 = new Thread(p.GetWife);
                th3.Start();
                AutoResetEvent.WaitAll(p.autoEvents);
    
                p.ShowHappiness();
            }
    
         
        }
    
        public class Person
        {
            public AutoResetEvent[] autoEvents;
            public Person()
            {
                autoEvents = new AutoResetEvent[]
                {
                    new AutoResetEvent(false),
                    new AutoResetEvent(false),
                    new AutoResetEvent(false)
                };
            }
            public void GetCar()
            {
                Console.WriteLine("捡到宝马");
                autoEvents[0].Set();
            }
            public void GetHome()
            {
                Console.WriteLine("赚到房子");
                autoEvents[1].Set();
            }
            public void GetWife()
            {
                Console.WriteLine("骗到老婆");
                autoEvents[2].Set();
            }
            public void ShowHappiness()
            {
                Console.WriteLine("好成功哦,好幸福!!!~~~");
            }
        }
    }
    复制代码

     

    例程3 异步回调

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    namespace AutoResetEventTest
    {
        class Program
        {
            public delegate int TaskDelegate(object obj, int ms);
    
            public static int GouDui(object obj, int ms)
            {
                Thread t = Thread.CurrentThread;
                t.Name = "灰太狼";
                Console.WriteLine("老板给了{0}元,让伟大的{1}来勾引你,识相的话赶紧上钩", obj.ToString(), t.Name);
                Thread.Sleep(ms);
                return 3000;
            }
    
            static void TakesAWhileCompleted(IAsyncResult ar)
            {
                //判断IAsyncResult对象是否有效,为空则抛出异常
                if(ar == null)
                {
                    throw new ArgumentNullException("ar");
                }
    
                //将ar对象中AsyncState属性强类型转换为TaskDelegate委托类型
                TaskDelegate d1 = ar.AsyncState as TaskDelegate;
                //跟踪检查d1是否有效,如果无效则显示提示消息
                System.Diagnostics.Trace.Assert(d1 != null,"无效的对象类型");
                //执行委托方法,并将结果交给变量result
                int result = d1.EndInvoke(ar);
    
                Console.WriteLine("结果泡了{0}个漂漂的mm",result);
            }
    
            static void Main(string[] args)
            {
                Thread t1 = Thread.CurrentThread;
                t1.Name = "单行道酒吧";
    
                Console.WriteLine("去{0}给我勾搭几个mm回来!超时每秒抠你100块工资", t1.Name);
    
                //为委托指定执行方法
                TaskDelegate t = GouDui;
                //使用魏国的BeginInvoke方法为所委托的方法赋值,并将执行结果交给IasyncResult接口
                IAsyncResult ir = t.BeginInvoke(600000, 1000 * new Random().Next(5), TakesAWhileCompleted, t);
    
                //Thread.Sleep(2000);
    
                //int i = 0;
                //while (!ir.IsCompleted)
                //{
                //    i++;
                //    Console.WriteLine(i.ToString());
    
    
                //    //方法1 
                //    //Thread.Sleep(100);
                //    //方法2
                //    if (ir.AsyncWaitHandle.WaitOne(100, false))
                //    {
                //        Console.WriteLine("怎么还不回来,再扣就把钱扣完了!");
                //        break;
                //    }
                //}
    
                ////获取委托方法执行后返回的值
                //int result = t.EndInvoke(ir);
                //Console.WriteLine("报告老板,我一共给你勾兑了{0}个超级mm", result.ToString());
                //if (i >= 1)
                //{
                //    Console.WriteLine("非常好,课时你耽误了{0}个小时,所以扣除你{1}块的报酬", i.ToString(), (100 * i).ToString());
                //}
                //else
                //{
                //    Console.WriteLine("小伙子不错哦。哥很欣赏你!");
                //}
                Console.ReadKey();
            }
    
    
        }
    }
    复制代码

    转载于:https://www.cnblogs.com/lxc-binary/p/3616245.html

    展开全文
  • 关于FindWindow PostMessage SendMessage PeekMessage 的两个例子
  • 下面在循环部分修改代码就得到了异步通信的第二种方法: 使 用与 IAsyncResult 相关的等待句 柄 [csharp] view plain copy print ? // 如果委托还没有执行完就开始循环     while  (!...

    作者:显天

    转自:http://blog.csdn.net/yixiantian7/article/details/10363513


    第一次写关于技术原创····


    至于要用到题目说到的这种方法,大概是因为在程序执行一些耗时的操作的时候,为了使得界面上不至于处于卡死状态,就让这些耗时的操作放在一边慢慢执行,并用一些方法来监视这些工作执行的状态。在这个过程中我的主线程可以完成一些其他的工作,这叫磨刀不误砍柴工··嘿嘿


    关于异步委托,这里要用到里面的两个方法BeginInvoke 和 EndInvoke


    BeginInvoke 方法启动异步调用。 该方法与您需要异步执行的方法具有相同的参数,还有另外两个可选参数。 第一个参数是一个 AsyncCallback 委托,该委托引用在异步调用完成时要调用的方法。 第二个参数是一个用户定义的对象,该对象将信息传递到回调方法。 BeginInvoke 立即返回,不等待异步调用完成。 BeginInvoke 返回一个 IAsyncResult,后者可用于监视异步调用的进度。


    用代码讲解貌似简单一点·来一个三国·长坂坡

    1.     class Program  
    2.     {  
    3.  
    4. #region  三国·长板坡  
    5.         //定义一个委托类型  
    6.         public delegate int TaskDelegate(object obj, int ms);  
    7.   
    8.   
    9.         //定义一个静态方法 看这个方法的开头就知道,大概是委托将要调用的方法  
    10.         public static int ForFun(object obj, int ms)  
    11.         {  
    12.             Thread t = Thread.CurrentThread;  
    13.             t.Name = "张飞";  
    14.             Console.WriteLine("我有{0}在手,谁敢与我{1}大战三百回合", obj.ToString(), t.Name);  
    15.             Thread.Sleep(ms);  
    16.             return 1234;  
    17.         }  
    18.   
    19.         //主线程入口,这个也是我们的主要战场  
    20.         static void Main(string[] args)  
    21.         {  
    22.             Thread t1 = Thread.CurrentThread;  
    23.             t1.Name = "长坂坡";  
    24.   
    25.   
    26.             //主公的任务  
    27.             Console.WriteLine("赶紧去{0}把赵子龙和阿斗救回来", t1.Name);  
    28.   
    29.   
    30.             //为刚才委托指定方法,这里注意方法只需要提供方法名字就可以  
    31.             TaskDelegate t = ForFun;  
    32.             //使用委托的BeginIvoke方法为所委托耳方法赋值,并将执行结果交给IAsysResult接口  
    33.             IAsyncResult ir = t.BeginInvoke("青釭剑", 1000 * new Random().Next(5), nullnull);//new Random().Next(5)  返回一个小于所指定最大值的非负随机数    
    34.             //上面这个函数除了最后两个参数之前的参数都是那个委托方法需要的参数  
    35.   
    36.             //曹操的军队比想象中快  
    37.             Thread.Sleep(2000);  
    38.             int i = 0;//计数器  
    39.   
    40.             // 如果委托还没有执行完就开始循环  
    41.             while (!ir.IsCompleted)  
    42.             {  
    43.                 i++;  
    44.                 Console.WriteLine(i.ToString());  
    45.                 Thread.Sleep(100);  
    46.             }  
    47.             //获取委托方法执行以后的返回值  
    48.             int result = t.EndInvoke(ir);  
    49.   
    50.             Console.WriteLine("报告主公,曹军杀来,我奋力拼杀,斩敌{0}人", i.ToString());  
    51.   
    52.             if (i > 1)  
    53.             {  
    54.                 Console.WriteLine("辛苦飞哥了,你杀敌{0}人,应该奖励黄金{1}两", i.ToString(), (i * 100).ToString());  
    55.   
    56.             }  
    57.             else  
    58.             {  
    59.                 Console.WriteLine("既然是未有杀敌,那今天就不奖励你啦");  
    60.             }  
    61.             Console.Read();  
    62.         }  
    1用IAsyncResult中的IsCompleted 属性进行轮询判断是否完成

    2 BeginInvoke()的函数声明:

    public IAsyncResult BeginInvoke(

             <输入和输出变量>,回调函数callback , 附加信息AsyncState)

    3 函数返回值类型:

    public interface IAsyncResult

    {

            object AsyncState{ get;}  //如果有回调函数的话该参数用于保存要传递给回调函数的参数值

            WaitHandle AsyncWaitHandle{ get;}

            bool CompletedSynchronously{ get;}

            bool IsCompleted{ get;} //保存方法是否执行结束,我们可以通过该属性的值来判断异步方法是否执行结束

    }

    4 EndInvoke方法用于检索异步调用结果。

    方法声明:

          public <方法返回值类型>EndInvoke(<声明为ref或out的参数>, IAsyncResult result )

    5 EndInvoke 方法检索异步调用的结果。 在调用 BeginInvoke 之后随时可以调用该方法。 如果异步调用尚未完成,则 EndInvoke 会一直阻止调用线程,直到异步调用完成

    上面这个例子就是:使用轮询等待异步调用完成:使用IAsyncResult的IsCompleted属性来判断异步调用是否完成(

    IAsyncResult来检


    下面在循环部分修改代码就得到了异步通信的第二种方法:使用与IAsyncResult相关的等待句

    1. // 如果委托还没有执行完就开始循环  
    2.            while (!ir.IsCompleted)  
    3.            {  
    4.                i++;  
    5.                Console.WriteLine(i.ToString());  
    6.                if(ir.AsyncWaitHandle.WaitOne(100,true))  
    7.                {  
    8.                    Console.WriteLine("主公的救兵怎么还不到,老张我撑不住了");  
    9.                    break;  
    10.                }  
    11.               // Thread.Sleep(100);  
    12.            }  


    使用 IAsyncResult.AsyncWaitHandle 属性获取 WaitHandle,使用其 WaitOne 方法阻止执行,直至 WaitHandle 收到信号,然后调用 EndInvoke

    第三种异步委托的方法就是使用回调函数


    那就先写一个回调函数来使用······要注意回调函数一定是在辅助线程里面使用

    1. static void TakesWhileCompleted(IAsyncResult ar)  
    2.         {  
    3.             //如果为空则抛出异常  
    4.             if (ar == null)  
    5.                 throw new ArgumentNullException("ar");  
    6.             //将ar对象中IAsyncResult属性强类型为TaskDelegate委托类型  
    7.             TaskDelegate dl = ar.AsyncState as TaskDelegate;  
    8.             //跟踪检查dl是否有效,如果无效则显示提示消息  
    9.             System.Diagnostics.Trace.Assert(dl != null"无效的对象类型");  
    10.             //执行委托方法,并将结果交给变量Result  
    11.             int result = dl.EndInvoke(ar);  
    12.             //打印结果,这里显示方法“ForFun”所返回的值  
    13.             Console.WriteLine("老张我英勇非常,杀敌{0}人", result);  
    14.         }  
    回调函数部分未完待续·····



    展开全文
  • C#线程同步--线程通信

    2018-08-21 22:44:00
    线程通信方案:ManualResetEventSlim、ManualResetEvent、AutoResetEvent方案特性:提供线程通知的能力,没有接到通知前,线程必须等待,有先后顺序。 1、ManualResetEvent类 对象有两种信号量状态True和False。...

    问题抽象:当某个操作的执行必须依赖于另一个操作的完成时,需要有个机制来保证这种先后关系。
    线程通信方案:ManualResetEventSlim、ManualResetEvent、AutoResetEvent
    方案特性:提供线程通知的能力,没有接到通知前,线程必须等待,有先后顺序。

    1、ManualResetEvent类
         对象有两种信号量状态True和False。构造函数设置初始状态。简单来说,
         ◆ 如果构造函数由true创建,则第一次WaitOne()不会阻止线程的执行,而是等待Reset后的第二次WaitOne()才阻止线程执行。
         ◆ 如果构造函数有false创建,则WaitOne()必须等待Set()才能往下执行。
      一句话总结就是:是否忽略第一次阻塞。
      方法如下:
           ◆ WaitOne:该方法用于阻塞线程,默认是无限期的阻塞,支持设置等待时间,如果超时就放弃阻塞,不等了,继续往下执行;
           ◆ Set:手动修改信号量为True,也就是恢复线程执行;
           ◆ ReSet:重置状态; 重置后,又能WaitOne()啦

    using System;
    using System.Threading;
    
    namespace ConsoleApp1
    {
        class Program
        {
            //一开始设置为false才会等待收到信号才执行
            static ManualResetEvent mr = new ManualResetEvent(false);
            public static void Main()
            {
                Thread t = new Thread(Run);
                //启动辅助线程
                t.Start();
                //等待辅助线程执行完毕之后,主线程才继续执行
                Console.WriteLine("主线程一边做自己的事,一边等辅助线程执行!" + DateTime.Now.ToString("mm:ss"));
                mr.WaitOne();
                Console.WriteLine("收到信号,主线程继续执行" + DateTime.Now.ToString("mm:ss"));
                Console.ReadKey();
            }
    
            static void Run()
            {
                //模拟长时间任务
                Thread.Sleep(3000);
                Console.WriteLine("辅助线程长时间任务完成!" + DateTime.Now.ToString("mm:ss"));
                mr.Set();
            }
        }
    }
    Program

      在思维上,这个东西可以有两种用法,一种是让主线程等待辅助线程,一种是辅助线程等待主线程。
      但无论怎么用,都是让一个线程等待或唤醒另外一个线程。

      Reset方法调用示例

    using System;
    using System.Threading;
    
    namespace ConsoleApp1
    {
        class Program
        {
            //一开始设置为false,当遇到WaitOne()时,需要Set()才能继续执行
            static ManualResetEvent mr = new ManualResetEvent(false);
    
            public static void Main()
            {
                Thread t = new Thread(Run);
                Console.WriteLine("开始" + DateTime.Now.ToString("mm:ss"));
                t.Start();
                mr.WaitOne();
                Console.WriteLine("第一次等待完成!" + DateTime.Now.ToString("mm:ss"));
                mr.Reset();     //重置后,又能WaitOne()啦
                mr.WaitOne(3000);
                Console.WriteLine("第二次等待完成!" + DateTime.Now.ToString("mm:ss"));
                Console.ReadKey();
            }
    
            static void Run()
            {
                mr.Set();
                Thread.Sleep(2000);
                mr.Set();
            }
        }
    }
    Program

    如果以上代码不使用Reset,则直接输出第二次等待完成,而不会等待2秒。

    2、AutoResetEvent类
      AutoResetEvent与ManualResetEvent的区别在于AutoResetEvent 的WaitOne会改变信号量的值为false,让其等待阻塞。
      比如说初始信号量为True,如果WaitOne超时信号量将自动变为False,而ManualResetEvent则不会。
      第二个区别:
      ◆ ManualResetEvent:每次可以唤醒一个或多个线程
      ◆ AutoResetEvent:每次只能唤醒一个线程

    using System;
    using System.Threading;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static AutoResetEvent ar = new AutoResetEvent(true);
            public static void Main()
            {
                Thread t = new Thread(Run);
                t.Start();
    
                bool state = ar.WaitOne(1000);
                Console.WriteLine("当前的信号量状态:{0}", state);
    
                state = ar.WaitOne(1000);
                Console.WriteLine("再次WaitOne后现在的状态是:{0}", state);
    
                state = ar.WaitOne(1000);
                Console.WriteLine("再次WaitOne后现在的状态是:{0}", state);
    
                Console.ReadKey();
            }
    
            static void Run()
            {
                Console.WriteLine("当前时间" + DateTime.Now.ToString("mm:ss"));
            }
        }
    }
    Program

     

      AutoResetEvent 允许线程通过发信号互相通信。通常,此通信涉及线程需要独占访问的资源。
      线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号。如果 AutoResetEvent 处于非终止状态,则该线程阻塞,并等待当前控制资源的线程,通过调用 Set 发出资源可用的信号。调用 Set 向 AutoResetEvent 发信号以释放等待线程。AutoResetEvent 将保持终止状态,直到一个正在等待的线程被释放,然后自动返回非终止状态。如果没有任何线程在等待,则状态将无限期地保持为终止状态。可以通过将一个布尔值传递给构造函数来控制 AutoResetEvent 的初始状态,如果初始状态为终止状态,则为 true;否则为 false。
      通俗的来讲只有等myResetEven.Set()成功运行后,myResetEven.WaitOne()才能够获得运行机会;Set是发信号,WaitOne是等待信号,只有发了信号,等待的才会执行。如果不发的话,WaitOne后面的程序就永远不会执行。下面我们来举一个例子:我去书店买书,当我选中一本书后我会去收费处付钱,
    付好钱后再去仓库取书。这个顺序不能颠倒,我作为主线程,收费处和仓库做两个辅助线程,代码如下:

    using System;
    using System.Threading;
    
    namespace ConsoleApp1
    {
        class TestAutoReseEvent
        {
            static AutoResetEvent BuyBookEvent = new AutoResetEvent(false);
            static AutoResetEvent PayMoneyEvent = new AutoResetEvent(false);
            static AutoResetEvent GetBookEvent = new AutoResetEvent(false);
            static int number = 10;
    
            public static void Run()
            {
                Thread buyBookThread = new Thread(new ThreadStart(BuyBookProc));
                buyBookThread.Name = "买书线程";
                Thread payMoneyThread = new Thread(new ThreadStart(PayMoneyProc));
                payMoneyThread.Name = "付钱线程";
                Thread getBookThread = new Thread(new ThreadStart(GetBookProc));
                getBookThread.Name = "取书线程";
    
                buyBookThread.Start();
                payMoneyThread.Start();
                getBookThread.Start();
    
                buyBookThread.Join();
                payMoneyThread.Join();
                getBookThread.Join();
    
            }
    
            static void BuyBookProc()
            {
                while (number > 0)
                {
                    Console.WriteLine("{0}:数量{1}", Thread.CurrentThread.Name, number);
                    PayMoneyEvent.Set();
                    BuyBookEvent.WaitOne();
                    Console.WriteLine("------------------------------------------");
                    number--;
                }
            }
    
            static void PayMoneyProc()
            {
                while (number > 0)
                {
                    PayMoneyEvent.WaitOne();
                    Console.WriteLine("{0}:数量{1}", Thread.CurrentThread.Name, number);
                    GetBookEvent.Set();
                }
            }
    
            static void GetBookProc()
            {
                while (number > 0)
                {
                    GetBookEvent.WaitOne();
                    Console.WriteLine("{0}:数量{1}", Thread.CurrentThread.Name, number);
                    BuyBookEvent.Set();
                }
            }
        }
    }
    TestAutoReseEvent
    namespace ConsoleApp1
    {
        class Program
        {
            public static void Main()
            {
                TestAutoReseEvent.Run();
            }
        }
    }
    Program

    3、ManualResetEventSlim类
      ManualResetEventSlim是ManualResetEvent的混合版本,一直保持大门敞开直到手工调用Reset方法,
      Set() 相当于打开了大门从而允许准备好的线程接收信号并继续工作
      Reset() 相当于关闭了大门 此时已经准备好执行的信号量 则只能等到下次大门开启时才能够执行

    using System;
    using System.Threading;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            {
                var t1 = new Thread(() => TravelThroughGates("Thread 1", 5));
                var t2 = new Thread(() => TravelThroughGates("Thread 2", 6));
                var t3 = new Thread(() => TravelThroughGates("Thread 3", 12));
                t1.Start();
                t2.Start();
                t3.Start();
                Thread.Sleep(TimeSpan.FromSeconds(6));
                Console.WriteLine("The gates are now open!");
                _mainEvent.Set();
                Thread.Sleep(TimeSpan.FromSeconds(2));
                _mainEvent.Reset();
                Console.WriteLine("The gates have been closed!");
                Thread.Sleep(TimeSpan.FromSeconds(10));
                Console.WriteLine("The gates are now open for the second time!");
                _mainEvent.Set();
                Thread.Sleep(TimeSpan.FromSeconds(2));
                Console.WriteLine("The gates have been closed!");
                _mainEvent.Reset();
            }
    
            static void TravelThroughGates(string threadName, int seconds)
            {
                Console.WriteLine("{0} falls to sleep {1}", threadName, seconds);
                Thread.Sleep(TimeSpan.FromSeconds(seconds));
                Console.WriteLine("{0} waits for the gates to open!", threadName);
                _mainEvent.Wait();
                Console.WriteLine("{0} enters the gates!", threadName);
            }
            /// <summary>
            /// ManualResetEventSlim是ManualResetEvent的混合版本,一直保持大门敞开直到手工调用Reset方法,
            /// _mainEvent.Set 相当于打开了大门从而允许准备好的线程接收信号并继续工作
            /// _mainEvent.Reset 相当于关闭了大门 此时已经准备好执行的信号量 则只能等到下次大门开启时才能够执行
            /// </summary>
            static ManualResetEventSlim _mainEvent = new ManualResetEventSlim(false);
        }
    }
    Program

     

    转载于:https://www.cnblogs.com/scmail81/p/9514952.html

    展开全文
  • c#线程通信

    2019-01-04 21:14:04
    1:建立一个Socket对像; 2:用socket对像的Connect()方法以上面建立的EndPoint对像做为参数,向服务器发出连接请求; 3:如果连接成功,就用socket对像的Send()方法向服务器发送...5:通信结束后一定记得关闭socket;
  • c#线程通信

    2009-01-15 14:13:00
    c#线程通信2008-11-08 12:19using System;using System.Text;using System.Threading;namespace ThreadTest{ class Program { static void Main(string[] args) { 
  • C# 线程间互相通信

    2014-04-19 09:36:00
    C#线程间互相通信主要用到两个类:AutoResetEvent和ManualResetEvent. 一、AutoResetEvent AutoResetEvent 允许线程通过发信号互相通信,线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号。 如果 ...
  • C#线程通信

    2013-12-22 10:07:00
    A------>(Start一开始B和StartMethod的C就同时执行)---->(C执行完了,不管B有没有执行完,invokeThread把消息封送(invoke)给UI线程,然后自己等待)---->UI线程处理完butInvoke_Click消息后,处理invokeThread封送...
  • C#线程间互相通信主要用到两个类:AutoResetEvent和ManualResetEvent。 一、AutoResetEvent AutoResetEvent 允许线程通过发信号互相通信,线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号。 如果 Au....
  • 线程通信 1. 当线程之间有先后的依赖关系时,属于线程之间的通信问题。也就是后一个线程要等待别的一个或多个线程全部完成,才能开始下一步的工作。可以使用: WaitHandle Class WaitHandle类作为基类来使用的...
  • c#线程通信之委托(事件) 在研究c# 线程之间通信时,发现传统的方法大概有三种 ①全局变量,由于同一进程下的多个进程之间共享数据空间,所以使用全局变量是最简单的方法,但要记住使用volatile进行...
  • C#线程通信详解

    2015-12-14 13:48:00
    一、WaitHandler的类层次 可以看到 WaitHandle是 事件(EventWaitHandle)、互斥体(Mutex)、信号量(Sempahore)的父类。 WaitHandle我们最经常使用的方法,并是... 那么如何要解除它对当前线程的阻塞呢,那么就需要依...
  • 本文介绍C#通过接口与线程通信(捕获线程状态),并提供简单的示例代码供参考
  • 线程之间的通信是通过发信号来进行沟通的 ManualResetEvent: 1.ManualResetEvent,调用一次Set()允许继续全部阻塞线程,这是和AutoResetEvent的区别; 2.ManualResetEvent调用Set()后需要手动Reset(),将信号 设置...
  • C# UI跨线程通信

    2016-09-25 16:04:31
    C#编程环境中,不允许在工作线程中直接对主线程(UI线程)中的控件进行更新操作。因此,稍微复杂一点的程序,跨线程更新UI界面是非常常见的。目前,一般有以下几种方法可以实现在工作线程对UI控件的更新: 通过...
  • C# 委托与线程通信

    2019-09-25 13:48:54
    1、C#中的委托机制我简单理解为C++中的函数指针。 用法如下: 使用委托: public delegate string MessageDelegate(string message); public class M { public string T(string message) { return message;...
  • C#线程通信

    2013-03-29 16:07:57
    有两个线程 各自运行 现在第一个线程要通知另一个线程记录下东西 怎么通知啊?
  • C#线程通信-Invoke

    千次阅读 2011-06-08 01:05:00
    A------>(Start一开始B和StartMethod的C就同时执行)---->(C执行完了,不管B有没有执行完,invokeThread把消息封送(invoke)给UI线程,然后自己等待)---->UI线程处理完butInvoke_Click消息后,处理invokeThread封送...
  • c#线程间的通信

    2012-12-18 09:53:08
    来自:http://blog.csdn.net/jxncwzb/article/details/1600381 using System; using System.Text; using System.Threading; namespace ThreadTest {  class Program ... static void Main(string

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 823
精华内容 329
关键字:

c#线程通信

c# 订阅