回顾
    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("我也是成功人士了,哈哈。。。");
        }
    }
}