多线程常见处理

多线程间 任务取消 

//多线程并发任务,某个失败后,希望通知别的线程,都停下来,how?
                //Thread.Abort--终止线程;向当前线程抛一个异常然后终结任务;线程属于OS资源,可能不会立即停下来
                //Task不能外部终止任务,只能自己终止自己(上帝才能打败自己)

                //cts有个bool属性IsCancellationRequested 初始化是false
                //调用Cancel方法后变成true(不能再变回去),可以重复cancel
                try
                {
                    CancellationTokenSource cts = new CancellationTokenSource();
                    List<Task> taskList = new List<Task>();
                    for (int i = 0; i < 50; i++)
                    {
                        string name = $"btnThreadCore_Click_{i}";
                        taskList.Add(Task.Run(() =>
                        {
                            try
                            {
                                if (!cts.IsCancellationRequested)
                                    Console.WriteLine($"This is {name} 开始 ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");

                                Thread.Sleep(new Random().Next(50, 100));

                                if (name.Equals("btnThreadCore_Click_11"))
                                {
                                    throw new Exception("btnThreadCore_Click_11异常");
                                }
                                else if (name.Equals("btnThreadCore_Click_12"))
                                {
                                    throw new Exception("btnThreadCore_Click_12异常");
                                }
                                else if (name.Equals("btnThreadCore_Click_13"))
                                {
                                    cts.Cancel();
                                }
                                if (!cts.IsCancellationRequested)
                                {
                                    Console.WriteLine($"This is {name}成功结束 ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                                }
                                else
                                {
                                    Console.WriteLine($"This is {name}中途停止 ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                                    return;
                                }
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex.Message);
                                cts.Cancel();
                            }
                        }, cts.Token)); //传入token会在Cancel以后 全部取消任务
} //1 准备cts 2 try-catch-cancel 3 Action要随时判断IsCancellationRequested //尽快停止,肯定有延迟,在判断环节才会结束  Task.WaitAll(taskList.ToArray()); //如果线程还没启动,能不能就别启动了? //1 启动线程传递Token 2 异常抓取 //在Cancel时还没有启动的任务,就不启动了;也是抛异常,cts.Token.ThrowIfCancellationRequested  } catch (AggregateException aex) { foreach (var exception in aex.InnerExceptions) { Console.WriteLine(exception.Message); } } catch (Exception ex) { Console.WriteLine(ex.Message); }

 多线程 内存锁

//1 Lock解决多线程冲突
                //Lock是语法糖,Monitor.Enter,占据一个引用,别的线程就只能等着
                //推荐锁是private static readonly object,
                // A不能是Null,可以编译不能运行;
                //B 不推荐lock(this),外面如果也要用实例,就冲突了
                Test test = new Test();
                Task.Delay(1000).ContinueWith(t =>
                {
                    lock (test)
                    {
                        Console.WriteLine("*********Start**********");
                        Thread.Sleep(5000);
                        Console.WriteLine("*********End**********");
                    }
                });
                test.DoTest();

                //C 不应该是string; string在内存分配上是重用的,会冲突
                //D Lock里面的代码不要太多,这里是单线程的
                Test test = new Test();
                string student = "水煮鱼";
                Task.Delay(1000).ContinueWith(t =>
                {
                    lock (student)
                    {
                        Console.WriteLine("*********Start**********");
                        Thread.Sleep(5000);
                        Console.WriteLine("*********End**********");
                    }
                });
                test.DoTestString();


     public void DoTestString()
            {
                lock (this.Name)
                //递归调用,lock this  会不会死锁? 98%说会! 不会死锁!
                //这里是同一个线程,这个引用就是被这个线程所占据
                {
                    Thread.Sleep(500);
                    this.iDoTestNum++;
                    if (DateTime.Now.Day < 28 && this.iDoTestNum < 10)
                    {
                        Console.WriteLine($"This is {this.iDoTestNum}次 {DateTime.Now.Day}");
                        this.DoTestString();
                    }
                    else
                    {
                        Console.WriteLine("28号,课程结束!!");
                    }
                }
            }
            private int iDoTestNum = 0;
            private string Name = "水煮鱼";

 

多线程 安全集合

System.Collections.Concurrent.ConcurrentQueue<int>

 

posted @ 2020-04-12 12:43  爱如少年。  阅读(504)  评论(0编辑  收藏  举报