ThreadCore学习

1.线程中的异常处理

一般线程里面不允许出现异常,需要自己处理好,最好在线程里加个try catch,

复制代码
                #region 异常处理
                //线程里面的异常是被吞掉了,因为已经脱离了try 的范围了, WaitAll 抓到多线程里面全部的异常
                //线程里面不允许出现异常,自己处理好,最好在线程里加个try catch
                for (int i = 0; i < 20; i++)
                {
                    string name = string.Format($"btnThreadCore_Click_{i}");
                    Action<object> act = t =>
                    {
                            //try
                            //{
                            Thread.Sleep(2000);
                        if (t.ToString().Equals("btnThreadCore_Click_11"))
                        {
                            throw new Exception(string.Format($"{t}执行失败"));
                        }
                        if (t.ToString().Equals("btnThreadCore_Click_12"))
                        {
                            throw new Exception(string.Format($"{t}执行失败"));
                        }
                        Console.WriteLine("{0}执行成功", t);
                            //}
                            //catch (Exception ex)
                            //{
                            //    Console.WriteLine(ex.Message);
                            //}
                        };
                    taskList.Add(taskFactory.StartNew(act, name));
                }
                Task.WaitAll(taskList.ToArray());
            }
复制代码

除此之外,可以在主线程中加个Try Catch ,使用AggregaException 进行捕获异常,注意try中要使用Task.WaitAll ,保证线程都运行完成,才能捕获得到

复制代码
        try
{
       //多线程操作
Task.WaitAll(taskList.ToArray());
}
catch
(AggregateException aex) { foreach (var item in aex.InnerExceptions) { Console.WriteLine(item.Message+"jj"); } }
复制代码

2.线程取消:CancellationTokenSource

复制代码
                //多个线程并发,某个失败后,希望通知别的线程,都停下来
                //task是外部无法中止的
                //线程自己停止自己--公共的访问变量--修改它--线程不断的检测它
                //CancellationTokenSource去标志任务是否取消, Cancal 取消  IsCancellationRequested 是否已经取消了
                //Token 启动Task的时候传入,那么如果Cancel了,这个任务会放弃启动,抛出一个异常
                CancellationTokenSource cts = new CancellationTokenSource();//bool值
                for (int i = 0; i < 40; i++)
                {
                    string name = string.Format("btnThreadCore_Click{0}", i);
                    Action<object> act = t =>
                    {
                        try
                        {
                            Thread.Sleep(2000);
                            if (t.ToString().Equals("btnThreadCore_Click11"))
                            {
                                throw new Exception(string.Format("{0}执行失败", t));
                            }
                            if (t.ToString().Equals("btnThreadCore_Click12"))
                            {
                                throw new Exception(string.Format("{0}执行失败", t));
                            }
                            if (cts.IsCancellationRequested)
                            {
                                Console.WriteLine("{0}放弃执行", t);
                                return;
                            }
                            else
                            {
                                Console.WriteLine("{0}执行成功", t);
                            }
                        }
                        catch (Exception ex)
                        {
                            cts.Cancel();
                            Console.WriteLine(ex.Message + "oo");
                        }
                    };
                    taskList.Add(taskFactory.StartNew(act, name, cts.Token));
                }
                Task.WaitAll(taskList.ToArray());
复制代码

3.多线程临时变量需注意

复制代码
                //全程就只有一个i
                //全程有5个k
                for (int i = 0; i < 5; i++)
                {
                    int k = i;
                    Task.Run(() =>
                    {
                        Thread.Sleep(100);
                        Console.WriteLine(k);
                    });
                }
复制代码

4.线程安全:使用lock

复制代码
                //lock 解决,因为只有一个线程可以进去,没有并发,所以解决了问题,但是牺牲了性能
                //安全队列  ConcurrentQueue  一个线程去完成操作
                //
                for (int i = 0;i< 10000; i++)
                {
                    int newI = i;
                    taskList.Add(taskFactory.StartNew(() => 
                    {
                        lock (btnThreadCore_Click_Lock)//lock后的方法块,任意时刻只有一个线程可以进入,只能锁引用类型,不要用string,因为享元
                        {
                            TotalCount += 1;
                            IntList.Add(newI);
                        }

                        Monitor.Enter(btnThreadCore_Click_Lock); //和lock一样的效果
                        Monitor.Exit(btnThreadCore_Click_Lock);
                        
                    }));
                }
                Task.WaitAll(taskList.ToArray());
                Console.WriteLine(TotalCount);
                Console.WriteLine(IntList.Count());
复制代码

 5.Asyc await会成对使用,使用之后,方法名前也要加个Task;当遇到await后,后返回到主线程运行,当task的逻辑执行完之后,后执行方法后的逻辑

复制代码
        private static async Task<long> SumAsync()
        {
            Console.WriteLine("SumAsync 1111 start");
            long result = 0;
            await Task.Run(() =>
            {
                for (int k = 0; k < 10; k++)
                {
                    Console.WriteLine($"SumAsync {k} await Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
                    Thread.Sleep(1000);
                }
                for(long i = 0; i < 999999; i++)
                {
                    result += i;
                }
            });
            Console.WriteLine($"SumFactory 111 end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
            return result;
        }
复制代码
                Task<long> t = SumAsync();
                long lResult = t.Result;//这种也会等子线程,获取返回值,等待的部分相当于t.wait()
                t.Wait();

 

posted @   你好呀嗯嗯  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示