第四十三讲:线程通信与异步委托

来源:互联网 发布:linux关闭安全狗 编辑:程序博客网 时间:2024/06/05 20:33
回顾
    1. 线程分前台线程和后台线程,差别就在于是否会阻止主线程结束
    2. 线程异步是多线程同步执行,线程同步是在多线程遇到抢夺资源的时候防止多个线程打架
    3. 实例化Thread类的时候可以使用的委托有两个,分别是有参数 和 无参数
    4. 几个同样的线程,如果希望被优先执行,则需要为其设置优先级
    5. 暂停线程有堵塞,挂起,join等方式。
    
主要内容
    1. 线程通知机制
        AutoResetEvent是线程实现通知操作的重要方法。通常,AutoResetEvent用于通知正在等待线程已发生事件,允许线程通过发信号互相通信。
        
        AutoResetEvent事件对象提供给了我们这样的通知机制,让我们可以控制线程执行的先后顺序,它的常用方法如下:
            1. set:设置并发送信号
            2. Reset:重置信号,也就是使信号无效
            3. WaitOne:等待一个信号,如果没有信号到来则等待
            4. WaitAny:静态方法,等待一个信号数组,信号数组里面有任何信号到都可以,否则等待。
            5. WaitAll: 静态方法,等待一个信号数组,信号数组里的信号全部到齐才可以,否则等待。
            
        创建一个AutoResetEvent对象,构造方法里需要带一个bool型参数,如:
        AutoResetEvent myResetEvent=new AutoResetEvent(false);
        
        这个参数如果是false表示事件开始是无信号状态,当参数为true表示创建的事件开始有信号的,就相当于使用false参数创建事件后即调用了set方法。
        
            
    2. 线程通信实践
        1. 先写后读
        2. 美好人生
    3. 异步委托
        1. IAsyncResult
        2. 等待句柄

        3. 异步回调


有关这些个线程的学习,我也成了牵线木偶了,跟着练习做的,迷糊着就过来了,教程看了两三遍,知道了AutoResetEvent类是线程间通信中目前所知道的唯一的类,它的方法也不多,等待1个或多个信号的,发送信息的就一个set方法,接收又分实例和静态方法,一次接收多个信息的是AutoResetEvent数组等等。

线程异步操作就一个IAsyncResult这个接口,在这里用到了委托来携带方法,如果直接使用方法是不行的,我测试过了。同时如果想使用异步回调这个参数,那么第四个参数也是少不了的,因需要在异步回调中的收尾工作还需要这个委托来调用EndInvoke呢。

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace Con433{    //定义一个委托用来携带方法    public delegate int delegateDajiangyou(object o,int ms);    class Program    {        public static int Dajiangyou(object o, int ms)        {            Thread t = Thread.CurrentThread;            t.Name = "便利店";            Console.WriteLine("\n小明的妈妈给了小明{0}元钱,让小明到{1}打酱油!让他在{2}秒时间里多打几瓶回家\n",o,t.Name,ms);            Thread.Sleep(ms);//打酱油过程中            return (int)o / 20;        }        //异步回调函数        public static void asyncCallBack(IAsyncResult ia)        {            //先判断接口对象是否为空,为空则抛出异常            if (ia == null)                throw new ArgumentNullException("ia");            //将异步状态接口对象中的对象参数转换成委托类型,即是IsyncReult中的第四个参数            delegateDajiangyou dd = ia.AsyncState as delegateDajiangyou;            //使用代码追踪器,监测对象            System.Diagnostics.Trace.Assert(dd != null, "无效的对象");            //从异步状态收尾的方法中获取,异步状态开始调用的委托方法的执行结果或返回值            //没有IsyncResult中的第四个参数,dd将为空,即下面这一句将不被执行            int result = dd.EndInvoke(ia);            Console.WriteLine("\n小明的妈妈很高兴自己有个乖儿子,看了看小打回来的{0}瓶酱油,继续做饭!\n", result);        }        /// <summary>        /// 主函数入口        /// </summary>        /// <param name="args"></param>        static void Main(string[] args)        {            Thread t = Thread.CurrentThread;            t.Name = "家里";            Console.WriteLine("\n小明在{0},妈妈做饭木酱油了,且酱油用的太快,但小明懒,妈妈说回来给零花钱,小明很高兴。"+                "\n可妈妈但心小明半路玩耍耽误事,说,如果在规定的时间里回不来就从零花钱里扣除,迟到1000s,扣一块!",t.Name);            delegateDajiangyou xiaoming = Dajiangyou;            int ms=4000*new Random().Next(3);            //IAsyncResult类是表示异步操作状态,返回操作状态            //如果要使用第三个参数,则此语句以下的部分先进行注释            //实话,我也没怎么明白透这些类的具体的详细作用            //IAsyncResult ir = xiaoming.BeginInvoke(50, ms, null, null);            //第四个参数可以是任意对象,以便在异步回调函数中使用它            IAsyncResult ir = xiaoming.BeginInvoke(50, ms, asyncCallBack, xiaoming);            #region 使用异步回调参数时需要注释的部分            //Thread.Sleep(4000);            //int i = 0;//如果超过规定的时间,就开始扣钱            //if (ir.IsCompleted)            //{            //    Console.WriteLine("小明真妈妈心中听话的乖孩子,零花不要随便花,留着以后买铅笔!乖。。。");            //}            //else            //{            //    while (!ir.IsCompleted)            //    {            //        i++;            //        Console.WriteLine("{0}块钱没了", i);            //        //特别情况下,追加了这段代码            //        if (ir.AsyncWaitHandle.WaitOne(100, false))            //        {            //            //1000ms设定的是等待的条件,true/false是否在等待之前            //            Console.WriteLine("到现在还没把酱油买回来,这熊孩纸是不是又在路边玩起来,算了还是洗洗手出去找他回来吧!");            //            break;//停扣费,中断循环。            //        }            //        //Thread.Sleep(1000);            //    }            //}            //int result = xiaoming.EndInvoke(ir);//结束监测状态,返回方法执行的结果            //if (i > 0)            //{            //    Console.WriteLine("明明,你迟到了{0}秒钟,妈妈要算了一下,要从你所得的零花钱里扣除{1}块钱", i * 1000, i);            //}            //else            //{            //    Console.WriteLine("小明的妈妈很高兴自己有个乖儿子,看了看小打回来的{0}瓶酱油,继续做饭!", result);            //}             #endregion            Console.ReadKey();        }    }}

为了以后在做实例 或 项目中能有据可查,我把自己学到的,做的练习都贴上来了。个人见解的旁白,只代表个人的意见。建议无论是砖家还是叫兽说的话都不要全信,还是实例一下好些,实践出真知吗!


以下补充的是线程通信的简单实例:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace Con43{    class Program    {        static AutoResetEvent ar = new AutoResetEvent(false);//线程通信必须的一个类        static int num;        static void Main(string[] args)        {            //线程通信之读写            Thread t = Thread.CurrentThread;//获取当前线程            t.Name = "写线程";            Thread t2 = new Thread(Rthread);//读线程            t2.Start();            for (int i = 0; i < 20; i++)            {                num = i;                                Console.WriteLine("当前线程为:{0},发送值:{1}", t.Name, num);                ar.Set();//发送信号,实例方法                //尽管我用了锁,但如果没这1毫秒的阻塞,还是会出乱子                Thread.Sleep(1);//等读            }            t2.Abort();//终止读线程            Console.ReadKey();        }        public static void Rthread()        {            //读线程            Thread t = Thread.CurrentThread;            t.Name = "读线程";            while (true)//此线程一直在等待接收信息            {                lock (ar)                {                    ar.WaitOne();//等待一个信号,实例方法                    Console.WriteLine("{0},接收到的值是:{1}", t.Name, num);                    Thread.Sleep(1);//等写                }            }        }    }}

还有一个:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace Con432{    class Program    {        static void Main(string[] args)        {            person p = new person();            Thread[] array = {                             new Thread(p.che),                             new Thread(p.fang),                             new Thread(p.wife)                             };            foreach (Thread t in array)            {                t.Start();            }            if (AutoResetEvent.WaitAll(p.ar))            {                p.CGR();            }            Console.ReadKey();        }    }    /// <summary>    /// 我们人类奋斗的目标,车房媳妇,老师有心了    /// 哈哈。。。    /// </summary>    public class person    {        public AutoResetEvent[] ar;        public person()        {            ar = new AutoResetEvent[]            {                 new AutoResetEvent(false),                new AutoResetEvent(false),                new AutoResetEvent(false)            };        }        public void che()        {            ar[0].Set();            Console.WriteLine("车子有了!");        }        public void fang()        {            ar[1].Set();            Console.WriteLine("房子有了!");        }        public void wife()        {            ar[2].Set();            Console.WriteLine("媳妇有了!");        }        public void CGR()        {            Console.WriteLine("我也是成功人士了,哈哈。。。");        }    }}


0 0
原创粉丝点击