15.3 多线程3

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。

15.3.6 线程返回值

如果需要从线程的方法中获得计算的值,可以考虑使用模块级公共变量,在线程对应的方法中最后赋值给这个公共变量,参看【例 15.10】。

另外一个常见的方法是使用类。在类中声明一个公共变量(或属性),通过将类传递给线程,在线程调用的过程中,将最后结果存储到类的公共变量(或属性)。

【例 15.14【项目:code15-014】通过类获得线程返回值。

以下代码通过线程计算从0到某个正整数所有数字的和,将结果保留到clsSum.outputSum中,并在主线程中获得结果。具体代码如下:

    class clsSum

    {

        public int inputNum;

        public int outputSum;

    }

        static void Main(string[] args)

        {

            clsSum sumNumber = new clsSum();

            sumNumber.inputNum = 100;

            Thread thGetSum = new Thread(getSum);

            thGetSum.Start(sumNumber);

            thGetSum.Join();

            Console.WriteLine("和为:{0}", sumNumber.outputSum);

            Console.ReadKey();

        }

        static void getSum(object sumobj)

        {

            clsSum obj = (clsSum)sumobj;

            int sum = 0;

            for (int i = 0; i <= obj.inputNum; i++)

                sum += i;

            obj.outputSum = sum;

        }

运行结果如下图所示:

图15-14 通过类获得线程返回值

15.3.7 线程的运行进度

要获得线程的运行进度可以使用主线程通过不断读取类的值来获得子线程运行情况。

【例 15.15【项目:code15-015】获得线程的运行进度。

    class clsSum

    {

        //求和需要计算到的整数

        public int inputNum;

        //当前计算的整数

        public int currentNum;

        //总和

        public int outputSum;

    }

        static void Main(string[] args)

        {

            clsSum sumNumber = new clsSum();

            sumNumber.inputNum = 10;

            Thread thSum = new Thread(getSum);

            thSum.Start(sumNumber);

            //直到计算到了最后一个整数则退出循环

            while( sumNumber.currentNum < sumNumber.inputNum)

            {

                Console.WriteLine("当前计算到:{0}", sumNumber.currentNum);

                Thread.Sleep(100);

            }

            thSum.Join();

            Console.WriteLine("和为:{0}", sumNumber.outputSum);

            Console.ReadKey();

        }

        static void getSum(object sumobj)

        {

            clsSum obj = (clsSum)sumobj;

            int sum = 0;

            for(int i = 0;i<= obj.inputNum;i++)

            {

                sum += i;

                obj.currentNum = i;

                Thread.Sleep(100);

            }

            obj.outputSum = sum;

      }

运行结果如下图所示:

图15-15 获得线程的运行进度

可以看到调用子线程后,主线程不断地做循环调用,但是由系统控制主线程和子线程交替运行,导致进度并不是按照0至10的顺序出现。另外需要注意的是,需要调用Sleep方法防止主线程或子线程占用完Cpu。

获得线程运行进度另外一种高效的方法是通过类事件。在【例 15.15】中,主线程通过不断的循环来获取线程造成系统资源极大浪费,而通过类事件将大大减少资源占用。

【例 15.16【项目:code15-016】使用类事件获得线程运行进度。

    internal class Program

    {

        static void Main(string[] args)

        {

            clsSum sumNumber = new clsSum();

            sumNumber.inputNum = 10;

            sumNumber.MyEvent += sumNumber.sumNumber_eventCurrentNum;

            //线程调用类的方法

            Thread thSum = new Thread(sumNumber.getSum);

            thSum.Start();

            thSum.Join();

            Console.WriteLine("和为:" + sumNumber.outputSum);

            Console.ReadKey();

        }

    }

    class clsSum

    {

        //求和需要计算到的整数

        public int inputNum;

        //当前计算的整数

        public int outputSum;

        //声明事件

        public delegate void eventCurrentNum(int i);

        public event eventCurrentNum MyEvent;

        public void getSum()

        {

            // 声明事件

           

            int sum = 0;

            for(int i= 0;i<= inputNum;i++)

            {

                sum += i;

                //触发eventCurrentNum事件

                MyEvent?.Invoke(i);

            }

            outputSum = sum;

        }

        //处理事件

        public void sumNumber_eventCurrentNum(int currentNum)

        {

            Console.WriteLine("计算到:" + currentNum);

        }

    }

运行结果如下图所示:

图15-16 通过类的事件获得线程运行进度

代码分析:

1、在类clsSum中声明MyEvent事件,其参数是当前求和计算的数字;

2、在类clsSumgetSum方法中,每计算一个数字,就触发eventCurrentNum事件;

3、在Main方法中,通过sumNumber.MyEvent += sumNumber.sumNumber_eventCurrentNum; 语句在运行时将类的事件(MyEvent)与事件处理(sumNumber_eventCurrentNum)相关联;

4、建立线程,调用类clsSumgetSum方法

代码中甚至连Sleep都省略了,并且获得了正确的结果,【例 15.16】比【例 15.15】的方法更高效,在具体编程中应首先考虑这个方法。

15.3.8 终止线程

终止线程只需要采用Abort方法,在【例 15.9】中已经演示了从一个线程使用Abort方法来终止另一个线程。事实上,子线程很多时候都是需要长时间运算(如循环读写)之类,如果生硬地使用Abort方法常常会导致意想不到的问题。通常的做法是在线程内部循环的时候检测变量状态是否符合,符合则退出循环,完成收尾工作,然后结束该线程。

【例 15.17【项目:code15-017】使用变量判断是否跳出循环结束线程。

    class clsSum

    {

        public int inputNum;

        public int outputSum;

        //用于控制是否跳出循环,结束线程

        public bool abortThread = false;

        //声明委托

        public delegate void eventCurrentNum(int currentNum);

        //声明事件

        public event eventCurrentNum currentNum;

        public void getSum()

        {

            int sum = 0;

            for(int i   = 0;i<= inputNum;i++)

            {

                //先检查abortThread,如果为true就跳出循环

                if (abortThread == true)

                {

                    Console.WriteLine("停止计算。");

                    break;

                }

                else

                {

                    sum += i;

                    Console.WriteLine($"计算到{i}");

                    //触发eventCurrentNum事件

                    currentNum?.Invoke(i);

                }

             }

            outputSum = sum;

        }

    }

        public static clsSum sumNumber;

        static void Main(string[] args)

        {

            sumNumber = new clsSum();

            sumNumber.inputNum = 100;

            sumNumber.currentNum += sumNumber_eventCurrentNum;

            //线程调用类的方法

            Thread thSum = new Thread(sumNumber.getSum);

            thSum.Start();

            thSum.Join();

            Console.WriteLine("和为:" + sumNumber.outputSum);

            Console.ReadKey();

        }

        //处理类的事件

        private static void sumNumber_eventCurrentNum(int currentNum)

        {

            //如果当前求和的数为10,那么设置abortThreadtrue

            if (currentNum >= 10)

                sumNumber.abortThread = true;

        }

运行结果如下图所示:

图15-17 通过bool变量判断来结束线程

学习更多vb.net知识,请参看vb.net 教程 目录

学习更多C#知识,请参看C#教程 目录

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

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

相关文章

同步异步日志系统-日志落地模块的实现

功能&#xff1a;将格式化完成后的日志消息字符串&#xff0c;输出到指定的位置 扩展&#xff1a;支持同时将日志落地到不同的位置 位置分类&#xff1a; 1.标准输出 2.指定文件&#xff08;时候进行日志分析&#xff09; 3.滚动文件&#xff08;文件按照时间/大小进行滚动…

【Kubernetes】k8s 部署指南

1. k8s 入门 1.1 k8s 简介 需要最需要明确的就是&#xff1a;kubernetes&#xff08;简称 k8s &#xff09; 是一个 容器编排平台 &#xff0c;换句话说就是用来管理容器的&#xff0c;相信学过 Docker 的小伙伴对于容器这个概念并不陌生&#xff0c;打个比方&#xff1a;容器…

Spring AI接入DeepSeek:快速打造微应用

随着DeepSeek-R1的官宣开源&#xff0c;DeepSeek迅速成为AI领域的热门话题&#xff0c;吸引了大量开发者和研究者的关注。这一开源举措不仅推动了技术的普及&#xff0c;也促使更多企业和机构加入到开源生态中。例如&#xff0c;国内大厂X度于2月14日宣布将在未来几个月推出文新…

MyBatis映射文件常用元素详解与示例

引言 MyBatis是一个优秀的持久层框架&#xff0c;它支持定制化SQL、存储过程以及高级映射。MyBatis的配置文件和映射文件分离&#xff0c;映射文件用于定义SQL语句和结果映射。本文将介绍MyBatis映射文件中常用的元素及其示例用法。 一、基础CRUD元素 1. <mapper> 作用…

SqlDbx 是一款数据库管理工具资源分享

SqlDbx_Chs 是 SqlDbx 的中文版本。SqlDbx 是一款数据库管理工具&#xff0c;支持多种数据库系统&#xff0c;如 MySQL、Oracle、SQL Server、PostgreSQL 等&#xff0c;主要用于执行 SQL 查询、管理数据库对象及数据操作。 主要功能 SQL 查询执行&#xff1a;支持编写和运行…

Dav_笔记14:优化程序提示 HINTs -4

指定全局表提示 指定表的提示通常是指发生提示的DELETE&#xff0c;SELECT或UPDATE查询块中的表&#xff0c;而不是指语句引用的任何视图中的表。 如果要为显示在视图中的表指定提示&#xff0c;Oracle建议使用全局提示&#xff0c;而不是在视图中嵌入提示。 您可以使用包含具…

Python 文本探秘:正则表达式的易错迷宫穿越 -- 7. 正则表达式

正则表达式是 Python 中处理文本的强大武器&#xff0c;但它复杂的语法和规则构成了一个易错迷宫。本文深入剖析了正则表达式模式编写的错误、匹配规则的误解、性能优化的忽视等问题。通过大量的文本处理实例&#xff0c;展示了错误的正则表达式使用方式以及正确的解决方案。帮…

PPT工具集

PPT模版 免费下载 爱PPT优品PPTPPT之家第一PPTOfficePlus部分免费 AI生成PPT Kimi秘塔搜索 可以输入内容生成PPT大纲。

rocketmq-netty通信设计-request和response

1、NettyRemotingServer启动分析 org.apache.rocketmq.remoting.netty.NettyRemotingServer#start public void start() {this.defaultEventExecutorGroup new DefaultEventExecutorGroup(nettyServerConfig.getServerWorkerThreads(),new ThreadFactory() {private AtomicI…

Datawhale 数学建模导论二 笔记1

第6章 数据处理与拟合模型 本章主要涉及到的知识点有&#xff1a; 数据与大数据Python数据预处理常见的统计分析模型随机过程与随机模拟数据可视化 本章内容涉及到基础的概率论与数理统计理论&#xff0c;如果对这部分内容不熟悉&#xff0c;可以参考相关概率论与数理统计的…

git如何下载指定版本

要使用Git下载指定版本&#xff0c;可以通过以下步骤进行操作‌&#xff1a; ‌1. 使用Git命令行下载指定版本‌&#xff1a; 1.1 首先&#xff0c;使用git clone命令克隆整个git库到本地。例如&#xff1a;git clone [库的URL]。这将下载最新的代码到本地。‌ 1.2 进入克隆…

安卓基础(持续更新的笔记)

为什么要这样&#xff1a; // 创建请求体RequestBody body RequestBody.create(MediaType.parse("application/json; charsetutf-8"),jsonObject.toString()); jsonObject 就包含了一个 JSON 数据&#xff0c;它其实就是&#xff1a; {"name": "张…

Spring Boot应用开发

一、了解Spring Boot Spring Boot是一个基于Spring框架的开源Java基础框架&#xff0c;它可以帮助我们快速开发独立的、基于生产级的基于Spring框架的应用程序。简单来说&#xff0c;它就像是一个“超级助手”&#xff0c;帮你把很多复杂的配置都简化了&#xff0c;让你能更轻…

算法笔记——字典树

什么是字典树&#xff1f; 一棵字典树树就像一个小型字典一样&#xff0c;当你拿到一个字想去字典上查的时候&#xff08;以拼音查法为例&#xff09;&#xff0c;你会先查这个拼音的开头字母&#xff0c;然后在按需查找他下一个字母直到找到相对应的拼音才可以。字典树也是如此…

Python实现AWS Fargate自动化部署系统

一、背景介绍 在现代云原生应用开发中,自动化部署是提高开发效率和保证部署质量的关键。AWS Fargate作为一项无服务器计算引擎,可以让我们专注于应用程序开发而无需管理底层基础设施。本文将详细介绍如何使用Python实现AWS Fargate的完整自动化部署流程。 © ivwdcwso (ID…

单元测试整理

在国外软件开发中&#xff0c;单元测试必不可少&#xff0c;但是国内并不太重视这一块&#xff0c;一个好的单元测试可以提前发现很多问题&#xff0c;也减去和测试battle的时间 Spring单元测试 JUnit4 RunWith 指明单元测试框架 e.g. RunWith(SpringJUnit4ClassRunner.cla…

Unity Shader Graph 2D - Procedural程序化图形之渐变的正弦波形

前言 正弦波形也是一种常用、常见的程序化图形&#xff0c;合理的使用正弦波形会创作出一些有趣、美观和丰富的效果&#xff0c;本文将使用Unity Shader Graph来实现一个正弦波形效果&#xff0c;帮助理解和实践Unity Shader Graph以及正弦函数。 创建一个名为SineWave的Shader…

【WPSOffice】汇总

写在前面 PPT篇 幻灯片母版 通过母版功能统一幻灯片的样式、字体、颜色等&#xff0c;提高整体一致性。 智能抠图 选中图片&#xff0c;图片工具-》智能抠图。 统一设置模板样式 字体安装 查找到字体并安装。 在WPS PPT&#xff08;WPS演示&#xff09;中&#xff0c;以…

DeepSeek 助力 Vue 开发:打造丝滑的卡片(Card)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

Windows环境搭建ES集群

搭建步骤 下载安装包 下载链接&#xff1a;https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.27-windows-x86_64.zip 解压 解压并复制出3份 es-node1配置 config/elasticsearch.yml cluster.name: xixi-es-win node.name: node-1 path.data: D:\\wor…