多线程

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AsyncThreads
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnSync_Click(object sender, EventArgs e)
        {
            Console.WriteLine($"***btnSync_Click {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
            People p = new People();
            for (int i = 0; i < 5; i++)
            {
                string name = $"btnSync_Click_{i}";
                this.DoSomethingLong(p);
            }
            Console.WriteLine($"btnSync_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
        }

        private void btnAsync_Click(object sender, EventArgs e)
        {
            People p = new People();
            Console.WriteLine($"***btnASync_Click {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
            Action<People> action = this.DoSomethingLong;
            //action += s => Console.WriteLine("aaaa");//action要执行BeginInvoke只能注册一个方法
            for (int i = 0; i < 5; i++)
            {
                string name = $"btnSync_Click_{i}";
                action.BeginInvoke(p, null, null);
            }
            Console.WriteLine("btnASync_Click End");
        }

        private void btnAsyncAdvance_Click(object sender, EventArgs e)
        {
            Console.WriteLine($"***btnAsyncAdvance_Click {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
            Action<People> action = this.DoSomethingLong;
            People p = new People();
            IAsyncResult ar0 = null;
            //1 回调事件
            AsyncCallback asyncCallback = ar =>
            {
                Console.WriteLine($"btnAsyncAdvance_BeginInvoke End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {(ar.AsyncState as People).Name}");
            };
            ar0 = action.BeginInvoke(p, asyncCallback, p);//传入参数,回调事件,传给回调事件的参数

            //2 判断异步委托是否执行完成 
            //int i = 0;
            //while (!ar0.IsCompleted)
            //{
            //    if (i < 9)
            //    {
            //        Console.WriteLine($"中华民族觉醒{++i * 10}%");
            //    }
            //    else
            //    {
            //        Console.WriteLine($"中华民族觉醒99.9%");
            //    }
            //    Thread.Sleep(400);
            //}

            //3 等待异步委托完成
            //ar0.AsyncWaitHandle.WaitOne();
            //ar0.AsyncWaitHandle.WaitOne(-1);//无限等待
            //ar0.AsyncWaitHandle.WaitOne(500);//等待指定毫秒

            //4 EndInvoke等待异步委托完成
            action.EndInvoke(ar0);
            //EndInvoke还可以获取返回值
            {
                Func<int> func = () => System.DateTime.Now.Hour;
                IAsyncResult arfunc = func.BeginInvoke(ar =>
                {
                    //EndInvoke 也可以用在回调里面,但是一个BeginInvoke只能对应一个EndInvoke
                    //int arRst = func.EndInvoke(ar);
                    //Console.WriteLine($"arRst={arRst}");
                }, null);
                func.BeginInvoke(null, null);
                int rst = func.EndInvoke(arfunc);
                Console.WriteLine($"rst={rst}");
            }
            Console.WriteLine("中华民族觉醒-->看招!!!");

            Console.WriteLine("btnAsyncAdvance_Click End");
        }

        #region .NetFramework 1.0 出现Thread
        private void btnThread_Click(object sender, EventArgs e)
        {
            Console.WriteLine($"***btnASync_Click {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
            {
                //People p = new People();
                //p.Name = "小王";
                //ThreadStart method = () => this.DoSomethingLong(p);
                //Thread thread = new Thread(method);
                //thread.Start();
            }
            {
                //People p = new People();
                //p.Name = "大王";
                //ParameterizedThreadStart method = obj =>
                //{
                //    Thread.Sleep(5000);
                //    this.DoSomethingLong(p);
                //    Thread.Sleep(5000);
                //};
                //Thread thread = new Thread(method);
                //thread.Start("111");

                #region 不建议的写法
                //thread.Suspend();//挂起线程(已过时)
                //thread.Resume();//恢复线程(已过时)
                //thread.Abort();//停止线程(不是真停止,只能停止程序,不接收相应,但是启用的计算机资源并不会停,比如硬盘读写)
                //Thread.ResetAbort();//恢复停止的线程
                #endregion

                //等待方式1
                //while (thread.ThreadState != ThreadState.Stopped)
                //{
                //    Thread.Sleep(200);
                //}
                //等待方式2
                //thread.Join();//等待thread线程完成
                //thread.Join(200);//等待thread线程最多200ms

                //thread.Priority = ThreadPriority.Normal;//指定线程执行的优先级,但保证不了完成的优先级

                //thread.IsBackground = true;//后台线程,关闭主线程,后台线程结束
                //thread.IsBackground = false;//默认是false,前台线程,主线程关闭,不影响前台线程
            }
            {
                //People p = new People();
                //ThreadStart threadStart = () => this.DoSomethingLong(p);
                //Action actionCallback = () => Console.WriteLine("actionCallback");
                //ThreadWithCallback(threadStart, actionCallback);
            }

            {
                Func<int> func = () =>
                {
                    Console.WriteLine($"***func {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
                    Thread.Sleep(5000);
                    Console.WriteLine("func End");
                    return 521;
                };
                Func<int> funcRst = ThreadWithReturn(func);
                int rst = funcRst.Invoke();
                Console.WriteLine(rst);
            }
            Console.WriteLine("btnThread_Click End");
        }

        //封装一个没有返回值的异步带回调的方法
        private void ThreadWithCallback(ThreadStart threadStart, Action actionCallback)
        {
            ThreadStart ts = () =>
            {
                threadStart.Invoke();
                actionCallback.Invoke();
            };
            Thread thread = new Thread(ts);
            thread.Start();
        }

        //封装一个有返回值的异步的方法
        private Func<T> ThreadWithReturn<T>(Func<T> func)
        {
            //非阻塞
            //获取返回值的时候是阻塞的
            T t = default(T);
            ThreadStart ts = () =>
            {
                t = func.Invoke();
            };
            Thread thread = new Thread(ts);
            thread.Start();
            return () =>
            {
                thread.Join();
                return t;
            };
        }
        #endregion

        #region .NetFramework 2.0 出现ThreadPool
        private void btnThreadPool_Click(object sender, EventArgs e)
        {
            //线程池的线程都是后台线程
            //线程的创建和销毁交给线程池了,提高资源的利用率
            //控制线程的数量
            //People p = new People();
            //ThreadPool.QueueUserWorkItem(obj => this.DoSomethingLong(p));
            //ThreadPool.QueueUserWorkItem(this.DoSomething, p);

            //ThreadPool.GetMaxThreads(out int workerThreads, out int completionPortThreads);//2015还不支持传参时定义out变量

            #region  线程池设置的最大/最小线程数量
            {
                //线程池设置的最大/最小线程数量针对线程全局
                //委托异步调用/Task/Parrallel/async/await 等都是线程池的线程
                //直接new Thread的这种不受线程池设置的影响,但是new Thread会占用线程池的数量

                //int workerThreads = 0;
                //int completionPortThreads = 0;
                //int minWorkerThreads = 0;
                //int minCompletionPortThreads = 0;
                //ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
                //ThreadPool.GetMinThreads(out minWorkerThreads, out minCompletionPortThreads);
                //Console.WriteLine($"workerThreads:{workerThreads},completionPortThreads:{completionPortThreads}");
                //Console.WriteLine($"minWorkerThreads:{minWorkerThreads},minCompletionPortThreads:{minCompletionPortThreads}");
                //ThreadPool.SetMaxThreads(8, 8);//设置最大线程数  不能小于电脑核数  否则不起作用 
                //ThreadPool.SetMinThreads(2, 2);
                //ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
                //ThreadPool.GetMinThreads(out minWorkerThreads, out minCompletionPortThreads);
                //Console.WriteLine($"workerThreads:{workerThreads},completionPortThreads:{completionPortThreads}");
                //Console.WriteLine($"minWorkerThreads:{minWorkerThreads},minCompletionPortThreads:{minCompletionPortThreads}");
            }
            #endregion

            #region 等待
            //false默认关闭--Set开启--WaitOne等待Set后执行后面的代码
            //true默认开启--Reset关闭--Reset后WaitOne阻塞后面的代码

            //ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            //ThreadPool.QueueUserWorkItem(obj =>
            //{
            //    People p = new People();
            //    manualResetEvent.Reset();
            //    this.DoSomethingLong(p);
            //    manualResetEvent.Set();
            //});
            //Console.WriteLine("do something else...");
            //Console.WriteLine("do something else...");
            //Console.WriteLine("do something else...");
            //Console.WriteLine("do something else...");

            //manualResetEvent.WaitOne();
            //Console.WriteLine("btnThreadPool_Click End");
            #endregion

            #region 死锁(小心使用Set,避免多个线程之间等待的关系)
            {
                ThreadPool.SetMaxThreads(8, 8);
                ManualResetEvent manualResetEvent = new ManualResetEvent(false);
                for (int i = 0; i < 10; i++)
                {
                    int k = i;
                    ThreadPool.QueueUserWorkItem(obj =>
                    {
                        Console.WriteLine($"***ThreadPool {Thread.CurrentThread.ManagedThreadId.ToString("00")} k:{k}");
                        if (k == 9)
                            manualResetEvent.Set();
                        else
                            manualResetEvent.WaitOne();
                    });
                }
                if (manualResetEvent.WaitOne())
                {
                    Console.WriteLine($"All thread in threadpool had ended");
                }
            }
            #endregion

        }
        #endregion

        #region .NetFramework 3.0 出现Task
        private void btnTask_Click(object sender, EventArgs e)
        {
            //Task的线程都是基于线程池的
            Console.WriteLine($"***btnTask_Click {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");

            #region 启动方式
            //{
            //    Task task = new Task(() => DoSomethingLong(new People()));
            //    task.Start();
            //}
            //{
            //    Task task = Task.Run(() => DoSomethingLong(new People()));
            //}
            //{
            //    Task task = new TaskFactory().StartNew(() => DoSomethingLong(new People()));
            //}
            #endregion

            #region Sleep 和Delay
            //sleep 是同步等待
            //delay 是异步等待--延迟启动
            //{
            //    Console.WriteLine($"Sleep start");
            //    Stopwatch stopwatch = new Stopwatch();
            //    stopwatch.Start();
            //    Thread.Sleep(2000);
            //    //Task.Run(() => DoSomethingLong(new People()));
            //    stopwatch.Stop();
            //    Console.WriteLine($"耗时{stopwatch.ElapsedMilliseconds}");
            //    Console.WriteLine($"Sleep end");
            //}
            //{
            //    Console.WriteLine($"Delay start");
            //    Stopwatch stopwatch = new Stopwatch();
            //    stopwatch.Start();
            //    Task.Delay(2000).ContinueWith(t =>
            //    {
            //        stopwatch.Stop();
            //        Console.WriteLine($"耗时{stopwatch.ElapsedMilliseconds}");
            //        DoSomethingLong(new People());
            //    });
            //    Console.WriteLine($"Delay end");
            //}
            //{
            //    //ContinueWith 其实就是回调
            //    Task.Run(() => DoSomething(new People())).ContinueWith(t => Console.WriteLine($"回调 {Thread.CurrentThread.ManagedThreadId}"));
            //}
            //{
            //    //带返回值的线程
            //    Task<int> task = Task.Run<int>(() =>
            //    {
            //        Thread.Sleep(1000);
            //        return DateTime.Now.Year;
            //    });
            //    int rst = task.Result;
            //    Console.WriteLine(rst);
            //}
            #endregion

            #region 一个例子
            {
                //多线程用在什么地方?
                //可以并发执行的任务
                //相反,有顺序限制,不可分割的动作就用不了
                Console.WriteLine($"Eleven老师开始一学期的课程");
                Teach("lenssen_0");
                Teach("lenssen_1");
                Teach("lenssen_2");

                Console.WriteLine($"布置了一个期末测试项目");
                TaskFactory taskFactory = new TaskFactory();
                List<Task> taskList = new List<Task>();

                taskList.Add(Task.Run(() => Coding("小高", "充值")));
                //taskList.Add(Task.Run(() => Coding("小悦", "订单")));
                Task.Delay(0).ContinueWith((o, s) => Coding("小悦", "订单"), "小悦");//传入参数,供回调使用
                taskList.Add(taskFactory.StartNew(() => Coding("小王", "权限")));
                taskList.Add(taskFactory.StartNew(o => Coding("大王", "推送"), "大王"));//传入参数,供回调使用

                //非阻塞
                taskFactory.ContinueWhenAny(taskList.ToArray(), t => Console.WriteLine($"{t.AsyncState} 异步方式任意一个线程完成 {Thread.CurrentThread.ManagedThreadId}"));
                //小套路,可以把等待全部线程结束的子线程也放入线程列表中,这样保证该线程执行在阻塞的等待全部完成之前
                taskList.Add(taskFactory.ContinueWhenAll(taskList.ToArray(), t => Console.WriteLine($"异步方式全部线程完成 {Thread.CurrentThread.ManagedThreadId}")));

                //阻塞的
                Task.WaitAny(taskList.ToArray());
                Console.WriteLine("第一个模块已经完成");

                Task.WaitAll(taskList.ToArray());
                Console.WriteLine("项目完成,开始点评");
            }
            #endregion

            {
                //使用task并控制线程的数量
                //for (int i = 0; i < 1000; i++)
                //{
                //    int k = i;
                //    List<Task> taskList = new List<Task>();
                //    if (taskList.Count(t => t.Status != TaskStatus.RanToCompletion) > 19)
                //    {
                //        Task.WaitAny(taskList.ToArray());
                //        taskList = taskList.Where(t => t.Status != TaskStatus.RanToCompletion).ToList();
                //    }
                //    taskList.Add(Task.Run(() => Console.WriteLine($"明日复明日,明日何其多 {k}")));
                //}
            }

            Console.WriteLine("btnTask_Click End");
        }
        #endregion

        #region Parallel
        private void btnParallel_Click(object sender, EventArgs e)
        {
            //Parallel会让主线程参与多线程的计算,所以会阻塞
            Console.WriteLine($"***btnParallel_Click {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");

            //Parallel.Invoke(() => Console.WriteLine($"Parallel执行0 ThreadId:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"),
            //    () => Console.WriteLine($"Parallel执行1 ThreadId:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"),
            //    () => Console.WriteLine($"Parallel执行2 ThreadId:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"),
            //    () => Console.WriteLine($"Parallel执行3 ThreadId:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"));

            //Parallel.For(0, 5, i =>
            //{
            //    Console.WriteLine($"Parallel执行{i} ThreadId:{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
            //    Thread.Sleep(2000);//不加等待执行过快,全是主线程在跑
            //});

            //Parallel.ForEach(new int[] { 0, 1, 2, 3, 4 }, i =>
            //     {
            //         Console.WriteLine($"Parallel执行{i} ThreadId:{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
            //         Thread.Sleep(2000);//不加等待执行过快,全是主线程在跑
            //     });
            {
                //控制线程数量
                ParallelOptions parallelOptions = new ParallelOptions();
                parallelOptions.MaxDegreeOfParallelism = 3;//线程数量设为3
                Parallel.For(0, 10, parallelOptions, i =>
                 {
                     Console.WriteLine($"Parallel执行{i} ThreadId:{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                     Thread.Sleep(2000);//不加等待执行过快,全是主线程在跑
                 });
            }
            Console.WriteLine($"btnParallel_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
        }
        #endregion

        private void btnThreadCore_Click(object sender, EventArgs e)
        {
            //多线程中的异常会终结当前线程,不会影响其他线程,异常会被吞

            Console.WriteLine($"***btnThreadCore_Click {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");

            #region 异常处理
            //try
            //{
            //    List<Task> taskList = new List<Task>();
            //    for (int i = 0; i < 10; i++)
            //    {
            //        int k = i;
            //        taskList.Add(Task.Run(() =>
            //       {
            //           try
            //           {
            //               if (k == 3)
            //               {
            //                   throw new Exception("3异常");
            //               }
            //               else if (k == 6)
            //               {
            //                   throw new Exception("6异常");
            //               }
            //               Console.WriteLine($"***TaskRun_{k} {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
            //           }
            //           catch (Exception ex)//一般不允许线程里面出现错误,捕获异常,自己处理
            //           {
            //               Console.WriteLine(ex.Message);
            //           }
            //       }));
            //    }
            //    Task.WaitAll(taskList.ToArray());//可以捕获线程的异常
            //}
            //catch (AggregateException aex)//AggregateException  多线程异常
            //{
            //    foreach (var exce in aex.InnerExceptions)
            //    {
            //        Console.WriteLine(exce.Message);
            //    }
            //}
            //catch (Exception ex)
            //{
            //    Console.WriteLine(ex.Message);
            //}
            //通常不允许多线程里出现错误,所以要在多线程中加try-catch
            #endregion

            #region 线程取消  其实是多线程任务的终止,线程跑起来没法从外部取消
            //线程执行起来并不能从外部取消,所以要做到取消,只能是在线程执行前加判断和信号量,如果信号量改变,就不让线程启动,这样模拟多线程任务的终止
            //1.准备cts  2.try-catch-cts.Cancel 3.线程中取消的动作前判断IsCancellationRequested  4.信号量的发出到判断环节的接收 会有延迟
            //Task.Run(Action action, CancellationToken cancellationToken) 传cts.Token 进去,接收到信号,没有开始的线程就不启动了
            //CancellationTokenSource cts = new CancellationTokenSource();//信号量,初始化属性IsCancellationRequested是false
            //List<Task> taskList = new List<Task>();
            //try
            //{
            //    for (int i = 0; i <= 50; i++)
            //    {
            //        int k = i;
            //        taskList.Add(Task.Run(() =>
            //        {
            //            try
            //            {
            //                Console.WriteLine($"task_{k}_start {Thread.CurrentThread.ManagedThreadId}");
            //                Thread.Sleep(new Random().Next(5, 10) * 100);

            //                if (k == 8 || k == 10)
            //                {
            //                    throw new Exception($"task_{k}_err");
            //                }

            //                if (!cts.IsCancellationRequested)
            //                {
            //                    Console.WriteLine($"task_{k}_end");
            //                }
            //                else
            //                {
            //                    Console.WriteLine($"task_{k}_cancel");
            //                }
            //            }
            //            catch (Exception ex)
            //            {
            //                Console.WriteLine(ex.Message);
            //                cts.Cancel();
            //            }
            //        }, cts.Token));
            //    }
            //    Task.WaitAll(taskList.ToArray());//会引起cts.Token已经取消执行的线程报出异常
            //}
            //catch (AggregateException aex)//AggregateException  多线程异常
            //{
            //    foreach (var exce in aex.InnerExceptions)
            //    {
            //        Console.WriteLine(exce.Message);
            //    }
            //}
            //catch (Exception ex)
            //{
            //    Console.WriteLine(ex.Message);
            //}

            #endregion

            #region 临时变量
            //线程启动是需要时间的,此时i已经很快跑到5了
            //由于每个循环的k是一个新的变量,所以用k作为每次循环的标志
            //for (int i = 0; i < 5; i++)
            //{
            //    int k = i;
            //    Task.Run(() =>
            //    {
            //        Console.WriteLine($"task_{i}_{k}");
            //    });
            //}
            #endregion

            #region 线程安全 lock
            //1.全局变量、共享变量、静态变量、文件、数据库都要考虑线程安全的问题,凡是能被多个线程改变的东西,是要考虑安全的
            //  推荐写法:private static readonly object objLock = new Object();
            //  lock 锁的应该是引用类型
            //  lock(this)的问题,如果在类外要锁实例,会发生冲突   锁是针对多线程的,单线程是不起作用的
            //  lock(string) 如果类外锁的string内容与类内锁的内容相同,会发生冲突

            //2.线程安全的集合,都在这个域名下
            //  System.Collections.Concurrent.ConcurrentQueue<int> ccQueue = new System.Collections.Concurrent.ConcurrentQueue<int>();

            //3.数据分拆,避免多线程操作同一块数据

            {
                Test test = new Test();

                Task.Delay(1000).ContinueWith(t =>
                {
                    lock (test)//这个实例与Test类中的this冲突了,按先后顺序,一个锁执行完成,才会走另一个锁
                    {
                        Console.WriteLine("ContinueWith Start");
                        Thread.Sleep(1000);
                        Console.WriteLine("ContinueWith End");
                    }
                });

                test.TestLock();//递归的过程中这个锁是不起作用的,不会锁线程自己


                //string strMyLock = "小高";
                //Task.Delay(1000).ContinueWith(t =>
                //{
                //    lock (strMyLock)//这个实例与Test类中的strLock值一样 冲突了,按先后顺序,一个锁执行完成,才会走另一个锁
                //    {
                //        Console.WriteLine("ContinueWithString Start");
                //        Thread.Sleep(1000);
                //        Console.WriteLine("ContinueWithString End");
                //    }
                //});
                //test.TestLockString();
                Thread.Sleep(10000);
            }
            {
                for (int i = 0; i < 1000; i++)
                {
                    iSync++;
                }
                List<Task> taskList = new List<Task>();
                //不加锁,多线程赋值同一个全局变量是不安全的
                //for (int i = 0; i < 1000; i++)
                //{
                //    taskList.Add(Task.Run(() => iAsync++));
                //}

                for (int i = 0; i < 1000; i++)
                {
                    taskList.Add(Task.Run(() =>
                    {
                        lock (objLock)
                        {
                            iAsync++;
                        }
                    }));
                }
                Task.WaitAll(taskList.ToArray());
                Console.WriteLine($"iSync={iSync} iAsync={iAsync}");
            }
            #endregion
            Console.WriteLine("btnThreadCore_Click End");
        }

        private int iSync = 0;
        private int iAsync = 0;
        private static readonly object objLock = new object();
        public class Test
        {
            public void TestLock()
            {
                this.iTest++;
                lock (this)//递归的过程中这个锁是不起作用的,不会锁线程自己
                {
                    if (iTest < 10)
                    {
                        Thread.Sleep(500);
                        Console.WriteLine($"iTest={iTest}");
                        this.TestLock();
                    }
                    else
                    {
                        Console.WriteLine($"iTest={iTest}  end!!!!!!!!!");
                    }
                }
            }
            public void TestLockString()
            {
                this.iTest++;
                lock (strLock)//递归的过程中这个锁是不起作用的,不会锁线程自己
                {
                    if (iTest < 10)
                    {
                        Thread.Sleep(500);
                        Console.WriteLine($"iTestString={iTest}");
                        this.TestLockString();
                    }
                    else
                    {
                        Console.WriteLine($"iTestString={iTest}  end!!!!!!!!!");
                    }
                }
            }
            private int iTest = 0;
            private string strLock = "小高";
        }


        private void DoSomethingLong(People p)
        {
            Console.WriteLine($"***DoSomethingLong {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
            Console.WriteLine($"Name:{p.Name}");
            Thread.Sleep(4000);
            p.Name = "小高";
            Console.WriteLine("DoSomethingLong End");
        }

        private void DoSomething(object p)
        {
            People people = p as People;
            Console.WriteLine($"Name:{people?.Name}");
        }

        private void Teach(string lensson)
        {
            Console.WriteLine($"教授课程{lensson}");
        }

        private void Coding(string name, string mode)
        {
            Console.WriteLine($"{name}同学做{mode}模块 {Thread.CurrentThread.ManagedThreadId}");
            Thread.Sleep(1000);
        }

        public class People
        {
            private string _name;
            private readonly object obj = new object();
            public string Name
            {
                set
                {
                    lock (obj)
                    {
                        _name = value;
                    }
                }

                get { return _name; }
            }
        }
    }
}

 

双色球练习:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AsyncThreads
{
    public partial class Form2 : Form
    {
        private List<int> redList = new List<int>();
        private List<int> blueList = new List<int>();
        private CancellationTokenSource cts = new CancellationTokenSource();
        private static readonly object objLock = new object();
        List<Task> taskList = new List<Task>();
        public Form2()
        {
            InitializeComponent();
            this.btnStop.Enabled = false;
            for (int i = 0; i < 33; i++)
            {
                redList.Add(i + 1);
                if (i < 16)
                    blueList.Add(i + 1);
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            //多线程取随机数不能用Random,结果很可能相同
            //子线程不能操作UI,需要委托给主线程this.Invoke,这种其实是同步执行的
            this.btnStart.Enabled = false;
            foreach (var control in gbxResult.Controls)
            {
                if (control is Label)
                {
                    Label label = (Label)control;
                    if (label.Name.Equals("lab6"))
                    {
                        taskList.Add(Task.Run(() =>
                        {
                            while (!cts.IsCancellationRequested)
                            {
                                int number = GetDelayRandomNumber(0, 16);
                                this.Invoke(new Action(() => label.Text = number.ToString().PadLeft(2, '0')));
                            }
                        }));
                    }
                    else
                    {
                        taskList.Add(Task.Run(() =>
                        {
                            while (!cts.IsCancellationRequested)
                            {
                                int number = GetDelayRandomNumber(0, 33);
                                lock (objLock)
                                {
                                    List<int> intList = GetInterFaceNumber();
                                    if (!intList.Contains(number))
                                    {
                                        this.Invoke(new Action(() => label.Text = number.ToString().PadLeft(2, '0')));
                                    }
                                }
                            }
                        }));
                    }

                }
            }

            Task.Factory.ContinueWhenAll(taskList.ToArray(), t => ShowMessage());
            Task.Delay(10 * 1000).ContinueWith(t =>
            {
                this.Invoke(new Action(() => this.btnStop.Enabled = true));
            });

            #region 第一次写的差代码
            //for (int i = 0; i < 7; i++)
            //{
            //    int k = i;
            //    //多线程取随机数不能用Random,结果很可能相同
            //    //Random rdm = new Random();
            //    int number = 0;
            //    Task.Run(() =>
            //    {
            //        try
            //        {
            //            while (!cts.IsCancellationRequested)
            //            {
            //                //有重复需要去重,读取界面当前的数据,判断现在生成的这个数是否在界面中,这个步骤要加锁
            //                number = GetDelayRandomNumber(0, 33);
            //                if (k == 6)
            //                {
            //                    number = GetDelayRandomNumber(0, 16);
            //                }
            //                var label = gbxResult.Controls[k];
            //                //label.Text = number.ToString().PadLeft(2, '0');//子线程不能操作UI,需要委托给主线程this.Invoke
            //                this.Invoke(new Action(() => label.Text = number.ToString().PadLeft(2, '0')));
            //            };
            //        }
            //        catch (Exception ex)
            //        {
            //            Console.WriteLine(ex.Message);
            //        }
            //    });
            //}
            #endregion

        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            this.btnStart.Enabled = true;
            this.btnStop.Enabled = false;
            cts.Cancel();

            //获取此刻数据会有错误的,停止按钮点了,但是线程有可能还没结束,面板上的数据和最终的数据有可能是不一样的,
            //所以必须等待所有线程结束
            //但是不能在主线程WaitAll,因为子线程中有委托给主线程的动作,主线程WaitAll之后,子线程一直结束不了,会死锁
            //可以给WaitAll和打印最终数据包一个线程

            //Task.WaitAll(taskList.ToArray());//死锁
            //ShowMessage()

            //Task.Run(() =>
            //{
            //    Task.WaitAll(taskList.ToArray());
            //    ShowMessage();
            //});
        }

        //[min,max)
        private int GetDelayRandomNumber(int min, int max)
        {
            Thread.Sleep(GetRandomNumber(100, 300));
            return GetRandomNumber(min, max);
        }

        private int GetRandomNumber(int min, int max)
        {
            Guid guid = new Guid();
            string strGuid = guid.ToString();
            int seed = DateTime.Now.Millisecond;
            for (int i = 0; i < strGuid.Length; i++)
            {
                switch (strGuid[i])
                {
                    case 'a':
                    case 'b':
                    case 'c':
                    case 'd':
                    case 'e':
                        seed += 1; break;
                    case 'f':
                    case 'g':
                    case 'h':
                    case 'i':
                    case 'j':
                        seed += 2; break;
                    case 'k':
                    case 'l':
                    case 'm':
                    case 'n':
                    case 'o':
                        seed += 3; break;
                    case 'p':
                    case 'q':
                    case 'r':
                    case 's':
                    case 't':
                        seed += 4; break;
                    case 'u':
                    case 'v':
                    case 'w':
                    case 'x':
                    case 'y':
                    case 'z':
                    default:
                        seed += 5; break;
                }
            }
            Random rdm = new Random(seed);
            return rdm.Next(min, max);
        }

        private List<int> GetInterFaceNumber()
        {
            List<int> intList = new List<int>();
            foreach (Control control in gbxResult.Controls)
            {
                if (control is Label)
                {
                    Label label = (Label)control;
                    intList.Add(int.Parse(label.Text));
                }
            }
            return intList;
        }

        private void ShowMessage()
        {
            string redMsg = "红球:";
            string blueMsg = "蓝球:";
            foreach (Control control in gbxResult.Controls)
            {
                if (control is Label)
                {
                    Label label = (Label)control;
                    if (!label.Name.Equals("lab6"))
                    {
                        redMsg += label.Text + " ";
                    }
                    else
                    {
                        blueMsg += label.Text;
                    }
                }
            }
            MessageBox.Show(redMsg + blueMsg);
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值