C# .Net学习笔记—— 异步和多线程(异常处理)

一、异常处理

1、下面for循环20个线程,到11,12号的时候执行失败,这里我也用了try catch来捕获异常。

 private void button11_Click(object sender, EventArgs e){TaskFactory taskFactory = new TaskFactory();List<Task> taskList = new List<Task>();try{for (int i = 0; i < 20; i++){string name = string.Format($"Click_{i}");Action<object> act = t =>{Thread.Sleep(2000);if (t.ToString().Equals($"Click_11")){throw new Exception(string.Format($"{t} 执行失败"));}if (t.ToString().Equals($"Click_12")){throw new Exception(string.Format($"{t} 执行失败"));}Console.WriteLine("{0} 执行成功", t);};taskList.Add(taskFactory.StartNew(act, name));}}catch (AggregateException aex){foreach (var item in aex.InnerExceptions){Console.WriteLine(item.Message);}}catch (Exception ex){Console.WriteLine(ex);}}

打印出来发现并没有捕获到异常

那么我再新增一句:

Task.WaitAll(taskList.ToArray());

这样我们就可以成功捕获到异常了。 同时,我们也可以通过AggregateException,捕获到我们异常的数据。

 最开始我们抓不到异常,是因为系统跑出了try catch,我们抓不到。

WaitAll可以抓到多线程里面的所有异常

但是产生了一个新的问题,WaitAll会卡界面

线程里面的action不允许出现异常,需要自己处理好

二、线程取消

多个线程并发,某个失败后,希望别的线程停下来。

task外部无法中止,Thread.Abort不靠谱,因为线程是OS的资源,无法掌控啥时候取消

线程自己停止自己——公共的访问变量——修改它——线程不断的检测它(会有延迟)

CancellationTokenSource标志任务是否取消    Cancel 表示取消  IsCancellationRequested表示是否取消。

Token启动Task的时候传入,那么如果Cancel 了,这个任务就会放弃启动,抛出一个异常

private void button12_Click(object sender, EventArgs e){TaskFactory taskFactory = new TaskFactory();List<Task> taskList = new List<Task>();CancellationTokenSource cts = new CancellationTokenSource();  //bool值for (int i = 0; i < 20; i++){string name = $"Click_{i}";Action<object> act = t =>{try{Thread.Sleep(2000);if (t.ToString().Equals($"Click_11")){throw new Exception(string.Format($"{t} 执行失败"));}if (t.ToString().Equals($"Click_12")){throw new Exception(string.Format($"{t} 执行失败"));}//除了11和12抛异常,其他的我们检查一下。//如果已经取消了,那么我们放弃执行if (cts.IsCancellationRequested) //检查信号量{Console.WriteLine($"{t} 放弃执行");return;}//如果还没取消了,那么我们正确执行else{Console.WriteLine($"{t} 执行成功");}}catch (Exception ex){cts.Cancel();Console.WriteLine(ex.Message);}};taskList.Add(taskFactory.StartNew(act, name, cts.Token));}Task.WaitAll(taskList.ToArray());}

 三、多线程的临时变量

1、闭包问题

       private void button13_Click(object sender, EventArgs e){for (int i = 0; i < 5; i++) {int k = i;Task.Run(() => {Thread.Sleep(100);Console.WriteLine(k);});}}

 四、多线程的线程安全问题

抛出问题:

private void button14_Click(object sender, EventArgs e){TaskFactory taskFactory = new TaskFactory();List<Task> taskList = new List<Task>();int totalCount = 0;List<int> intList = new List<int>();for (int i = 0; i < 10000; i++){int newi = i;taskList.Add(taskFactory.StartNew(() => {totalCount += 1;intList.Add(newi);}));}Task.WaitAll(taskList.ToArray());Console.WriteLine(totalCount);Console.WriteLine(intList.Count);}

这里我声明了一个int类型的临时变量和一个List<int>类型的临时变量,让他们嵌套在多线程内进行累加。

 可以发现打印出来的数目并不一致,并且都小于10000

这就是线程安全的问题,是多个线程同时操作同一变量导致的。

对于共有变量:都能访问的局部变量/全局变量/数据库的值/硬盘文件

 我们尝试加上锁(Lock)(Lock可以算是一种语法糖)。

 private static readonly object btnThreadCore_Click_Lock = new object();private void button14_Click(object sender, EventArgs e){TaskFactory taskFactory = new TaskFactory();List<Task> taskList = new List<Task>();int totalCount = 0;List<int> intList = new List<int>();for (int i = 0; i < 10000; i++){int newi = i;taskList.Add(taskFactory.StartNew(() => {lock (btnThreadCore_Click_Lock){totalCount += 1;intList.Add(newi);}}));}Task.WaitAll(taskList.ToArray());Console.WriteLine(totalCount);Console.WriteLine(intList.Count);}

发现打印出来的数量都正常。

因为lock后的方法块,任意时刻只有一个线程可以进入

1、Lock介绍:

介绍:Lock等同于Monitor.Enter(btnThreadCore_Click_Lock); 

        离开等同于调用了Monitor.Exit();

限制:Lock只能锁引用类型(占用引用链接),不要用string,因为享元

        微软提供的标准写法:

        private static readonly object btnThreadCore_Click_Lock = new object();

        Lock 最好锁private的,防止外面也去lock

        static 全场唯一 ,避免不同实例锁的不同

        readonly 只读,不要改动

        object 表示引用

lock(this)每次实例化都是不同的锁,同一个实例时相同的锁

但是这个实例别人也能访问到,别人也能锁定

缺点:

 Lock解决,因为只有一个线程可以进去,没有并发,所以解决了问题,但是牺牲了性能,所以要尽量缩小lock的范围

2、安全队列(ConcurrentQueue):

最后还是需要一个线程完成操作

3、最好的方法就是不要冲突——数据拆分,避免冲突!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/662518.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

回归预测 | Matlab基于POA-LSSVM鹈鹕算法算法优化最小二乘支持向量机的数据多输入单输出回归预测

回归预测 | Matlab基于POA-LSSVM鹈鹕算法算法优化最小二乘支持向量机的数据多输入单输出回归预测 目录 回归预测 | Matlab基于POA-LSSVM鹈鹕算法算法优化最小二乘支持向量机的数据多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab基于POA-LSSVM…

【数据结构与算法】之排序系列-20240201

【数据结构与算法】之排序系列-20240201 一、88. 合并两个有序数组二、169. 多数元素三、217. 存在重复元素四、242. 有效的字母异位词五、268. 丢失的数字六、349. 两个数组的交集七、350. 两个数组的交集 II 一、88. 合并两个有序数组 简单 给你两个按 非递减顺序 排列的整数…

【Uni-App】运行微信小程序时报错routeDone with a webviewId 2 that is not the current page

使用HBuilderX开发微信小程序&#xff0c;运行项目的时有可能会出现routeDone with a webviewId 1 that is not the current page的报错&#xff0c;但不影响运行。如果强迫症介意的话&#xff0c;可以考下面的方法进行修复。 产生原因 由于微信开发者工具的调试基础库处于灰度…

私域流量如何变现?一站式产品体系搭建与运营策略大公开

在互联网日新月异的今天&#xff0c;我们面临着人口红利逐渐消失的问题&#xff0c;各行各业的广告投放获客成本也在不断上涨。为了降低成本并提高用户转化和复购率&#xff0c;我们需要寻找新的解决方案。此时&#xff0c;私域流量的概念应运而生&#xff0c;成为了一个值得考…

【计算机二级考试C语言】C递归

目录 C 递归 数的阶乘 实例 斐波那契数列 实例 C 递归 递归指的是在函数的定义中使用函数自身的方法。 举个例子&#xff1a; 从前有座山&#xff0c;山里有座庙&#xff0c;庙里有个老和尚&#xff0c;正在给小和尚讲故事呢&#xff01;故事是什么呢&#xff1f;"从…

Python 的 pass 语句到底是什么?

Python 中的 pass 语句是一个简单的概念&#xff0c;即使没有编程经验的初学者也能很快掌握。官方文档提供了非常简单的介绍&#xff0c;下面的三个示例可以让我们快速了解如何使用它。 pass 本质上是一个空操作&#xff0c;除了允许解释器在跳过语法之前检查语法是否有效之外&…

apk反编译修改教程系列---修改apk的默认颜色 布局颜色 手机电脑同步演示【十】

往期教程&#xff1a; apk反编译修改教程系列-----修改apk应用名称 任意修改名称 签名【一】 apk反编译修改教程系列-----任意修改apk版本号 版本名 防止自动更新【二】 apk反编译修改教程系列-----修改apk中的图片 任意更换apk桌面图片【三】 apk反编译修改教程系列---简单…

PMP备考的三个阶段及学习方法分享

PMP证书是项目管理必备的关键技能证书&#xff0c;是具备进行项目管理的重要技能体现。无论升职加薪&#xff0c;还是从事项目管理工作&#xff0c;都非常重要。 个人主要从事产品开发工作&#xff0c;开始逐渐承担一些项目经理角色&#xff0c;但目前项目管理知识薄弱&#x…

深度剖析Sentinel热点规则

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 深度剖析Sentinel热点规则 前言核心概念解析&#xff1a;数字守护者的起源核心概念解析&#xff1a;简单示例演示&#xff1a; 参数索引&#xff1a;规则的基石参数索引的作用&#xff1a;不同场景下选…

sqli.labs靶场(23关到28a关)

23、第二十三关 id1单引号闭合 找位置1 and 12 union select 1,2,3 爆库&#xff1a;1 and 12 union select 1,2,database() 爆表名&#xff1a;1 and 12 union select 1,2,group_concat(table_name) from information_schema.tables where table_schemasecurity 爆字段&#…

git修改密码后mac使用sourceTree出现Authentication failed错误

1、退出sourceTree 2、在钥匙串中删除git对应站点Access Key 3、执行命令&#xff1a;git config --system --unset credential.helper 4、重新启动sourceTree&#xff0c;这时会弹出输入密码框&#xff0c;重新输入密码即可

C/C++ C++入门

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a;C_仍有未知等待探索的博客-CSDN博客 目录 一、C关键字 二、命名空间 1、区别 1. C语言 ​编辑 2. C 2、命名空间定义 3、命名空间的使用 三、C输入&输出 四、缺省参数 五、函数重载 六、引用 …

Nijijourney V6版本动漫图像生成模型发布

简介 这是一个最先进的AI&#xff0c;可以绘制任何二次元风格的绘画&#xff01;这是一个由 Spellbrush 与 Midjourney 所共同设计开发的魔法般工具。无论您是在寻找可爱的Q版角色还是充满动感的动作场景&#xff0c;niji・journey 都能将您的想象变为现实。 功能介绍 - 增强…

第1章 简单使用 Linux

第1章 简单使用 Linux 1.1 Linux 的组成 1.2 远程连接 首先以 root 用户登录到 Linux 系统&#xff0c;然后在 Terminal 终端上输入 ip add 命令&#xff0c;来查看 IP 地址。 上图中的 192.168.72.128 就是 IP 地址。 然后打开 XShell 远程连接工具。 然后在命令提示符下输…

【Django开发】0到1开发美多商城项目第3篇:用户注册业务实现(附代码,已分享)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论django商城项目相关知识。项目利用Django框架开发一套前后端不分离的商城项目&#xff08;4.0版本&#xff09;含代码和文档。功能包括前后端不分离&#xff0c;方便SEO。采用Django Jinja2模板引擎 Vue.js实现前后端…

人脸识别的多样化和稀疏关注对姿势变化和遮挡具有鲁棒性

DSA-Face: Diverse and Sparse Attentions for Face Recognition Robust to Pose Variation and Occlusion 一、创新点 1.提出了成对自我对比注意力来强制模型提取不同的局部特征&#xff1b; 2.设计注意力稀疏性损失是为了鼓励注意力图中的稀疏反应&#xff0c;阻止对分散注意…

C++ Web 编程

什么是 CGI&#xff1f; 公共网关接口&#xff08;CGI&#xff09;&#xff0c;是一套标准&#xff0c;定义了信息是如何在 Web 服务器和客户端脚本之间进行交换的。CGI 规范目前是由 NCSA 维护的&#xff0c;NCSA 定义 CGI 如下&#xff1a;公共网关接口&#xff08;CGI&…

passband, transition band and stopband

passband, transition band and stopband 引言正文 引言 这里给大家介绍一下 passband, transition band 和 stopband 的区别。 正文 如图所示&#xff0c;左侧和右侧比较高的部分是 passband。中间最低的部分是 stopband。而 passband 与 stopband 的连接区域被叫做 transit…

12款神级idea插件,让你少些80%代码

日常的业务功能开发&#xff0c;大部分情况下&#xff0c;核心代码差不多只占了项目的20%&#xff0c;剩下的80% 基本就是一些体力活&#xff0c;配置项等&#xff1b;这80%的代码&#xff0c;却消耗了我们大量的时间&#xff0c;而这部分代码&#xff0c;也不会对我们带来大的…

性能测试工具之工作原理及意义

随着软件系统的不断复杂和用户需求的不断增加&#xff0c;对于软件性能的要求也变得越来越高。性能测试工具成为确保应用程序在各种条件下都能提供卓越性能的关键组成部分。本文将深入解析性能测试工具的工作原理&#xff0c;以便更好地理解这些工具在保障系统性能方面的重要性…