C#线程基础(线程启动和停止)

目录

一、关于线程

二、示例 

三、生成效果


一、关于线程

        在使用多线程前要先引用命名空间System.Threading,引用命名空间后就可以在需要的地方方便地创建并使用线程。

        创建线程对象的构造方法中使用了ThreadStart()委托,当线程开始执行时,将会执行委托中定义的方法。通过IsBackground属性设置线程为后台线程,调用线程对象的Start方法启动线程,开始执行。CancellationToken方法终止线程。

         创建的线程分为前台线程和后台线程,通过线程对象的IsBackground属性可以设置线程为前台线程或后台线程。前台线程与后台线程的区别是,后台线程不会使托管程序处于运行状态。也就是说,如果进程停止所有前台线程,那么系统会认为此进程处于非运行状态,将会停止所有后台线程并关闭。

        适当地使用线程,可以增加程序的运行效率,使程序运行更加流畅,但是线程间的同步问题也显得尤为重要,可以使用线程锁或监视器有效地处理线程同步问题。

二、示例 

// 线程技术
// 使用随机对象产生一个1~100之间的整数,单击“开始”时,动态生成100个按钮并开始计时;
// 单击事件:按钮上的数字<随机数,那么被单击的按钮变为红色,并显示字符串“小”;
// 单击事件:按钮上的数字>随机数,那么被单击的按钮变为红色,并显示字符串“大”;
// 单击事件:按钮上的数字=随机数就会弹出消息框,提示已经猜对了数字,并显示用时及猜测次数。
namespace _033
{
    public partial class Form1 : Form
    {
        private Button? button1;
        private Label? label1;
        private Label? label2;
        private Label? label3;
        private Label? label4;
        Thread? thread_1;                    //定义线程
        readonly Random random_num = new();  //定义随机数对象
        int Temp_int_num;                    //定义变量用于存放存机数

        public Form1()
        {
            InitializeComponent();
            Load += Form1_Load;
        }
        private void Form1_Load(object? sender, EventArgs e)
        {
            // 
            // button1
            // 
            button1 = new Button
            {
                Location = new Point(30, 22),
                Name = "button1",
                Size = new Size(75, 23),
                TabIndex = 0,
                Text = "开始",
                UseVisualStyleBackColor = true
            };
            button1.Click += Button1_Click;
            // 
            // label1
            // 
            label1 = new Label
            {
                AutoSize = true,
                Location = new Point(206, 28),
                Name = "label1",
                Size = new Size(44, 17),
                TabIndex = 1,
                Text = "计时:"
            };
            // 
            // label2
            // 
            label2 = new Label
            {
                AutoSize = true,
                Location = new Point(256, 28),
                Name = "label2",
                Size = new Size(0, 17),
                TabIndex = 2
            };
            // 
            // label3
            // 
            label3 = new Label
            {
                AutoSize = true,
                Location = new Point(305, 28),
                Name = "label3",
                Size = new Size(20, 17),
                TabIndex = 3,
                Text = "秒"
            };
            // 
            // label4
            // 
            label4 = new Label
            {
                AutoSize = true,
                Location = new Point(115, 28),
                Name = "label4",
                Size = new Size(43, 17),
                TabIndex = 4,
                Text = ""
            };
            // 
            // Form1
            // 
            AutoScaleDimensions = new SizeF(7F, 17F);
            AutoScaleMode = AutoScaleMode.Font;
            ClientSize = new Size(379, 426);
            Controls.Add(label4);
            Controls.Add(label3);
            Controls.Add(label2);
            Controls.Add(label1);
            Controls.Add(button1);
            Name = "Form1";
            StartPosition = FormStartPosition.CenterScreen;
            Text = "猜数字";
            FormClosed += Form1_FormClosed;
        }

        private void Button1_Click(object? sender, EventArgs e)
        {
            RemoveControl();               //清空所有无用对象
            int bt_int_x = 10;             //X坐标初始值为10
            int bt_int_y = 60;             //Y坐标初始值为60
            for (int i = 0; i < 100; i++)  //添加100个按钮
            {
                Button bt = new()
                {
                    Text = (i + 1).ToString(),  //设置button按钮的文本值
                    Name = (i + 1).ToString(),  //设置button按钮的Name属性
                    Width = 35, 
                    Height = 35,   
                    Location = new Point(bt_int_x, bt_int_y)//设置button按钮的位置
                };
                bt.Click += new EventHandler(Bt_Click);     //定义button按钮的事件
                bt_int_x += 36;                             //设置下一个按钮的位置
                if ((i + 1) % 10 == 0)                      //每10个按钮就换行
                {
                    bt_int_x = 10;      //换行后重新设置X坐标
                    bt_int_y += 36;   //换行后重新设置Y坐标
                }
                Controls.Add(bt);   //将button按钮放入窗体控件集合中
            }
            thread_1 = new Thread(delegate ()       //新建一条线程使用匿名方法
                {
                    int P_int_count = 0;            //初始化计数器
                    while (true)                    //开始无限循环
                    {
                        P_int_count = ++P_int_count > 100000000 ? 0 : P_int_count;  //计数器累加
                        Invoke(                     //将代码交给主线程执行
                            (MethodInvoker)delegate //使用匿名方法
                            {
                                label2!.Text = P_int_count.ToString(); //窗体中显示计数
                            });
                        Thread.Sleep(1000);    //线程睡眠1秒
                    }
                })
            {
                IsBackground = true            //设置线程为后台线程
            };
            thread_1.Start();                  //开始执行线程
            Temp_int_num = random_num.Next(1, 100);//生成随机数
            label4!.Text = "随机数=" + Temp_int_num.ToString( );
            button1!.Enabled = false;          //停用开始按钮
        }
        /// <summary>
        /// 强行关闭窗体
        /// </summary>
        private void Form1_FormClosed(object? sender, FormClosedEventArgs e)
        {
            Environment.Exit(0);
        }
        /// <summary>
        /// 开始遍历100个按钮
        /// 清空窗体中动态生成的按钮
        /// </summary>
        void RemoveControl()
        {
            for (int i = 0; i < 100; i++)
            {
                if (Controls.ContainsKey((i + 1).ToString()))   //窗体中是否有此按钮
                {
                    for (int j = 0; j < Controls.Count; j++)    //遍历窗体控件集合
                    {
                        if (Controls[j].Name == (i + 1).ToString())//是否查找到按钮
                        {
                            Controls.RemoveAt(j);                  //删除指定按钮
                            break;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 用于查找窗体中Enable属性为False控件的数量
        /// 用于计算玩家有多少次没有猜中
        /// </summary>
        /// <returns>返回没有猜中数量</returns>
        string GetCount()
        {
            int P_int_temp = 0;                 //初始化计数器
            foreach (Control c in Controls)     //遍历控件集合
            {
                if (!c.Enabled) P_int_temp++;   //计数器累加
            }
            return P_int_temp.ToString();       //返回计数器信息
        }

        void Bt_Click(object? sender, EventArgs e)
        {
            Control? P_control = sender as Control; //将sender转换为control类型对象
            if (int.Parse(P_control!.Name) > Temp_int_num)
            {
                P_control.BackColor = Color.Red;     //设置按钮背景为红色
                P_control.Enabled = false;           //停用按钮
                P_control.Text = "大";               //更改按钮文本
            }
            if (int.Parse(P_control.Name) < Temp_int_num)
            {
                P_control.BackColor = Color.Red;     //设置按钮背景为红色
                P_control.Enabled = false;           //设置按钮停用
                P_control.Text = "小";               //更改按钮文本
            }
            if (int.Parse(P_control.Name) == Temp_int_num)
            {
                //thread1.Abort();
                CancellationToken cancellationToken = new();
                CancellationToken token = cancellationToken;
                Thread_Abort(token);
                MessageBox.Show(string.Format("恭喜你猜对了!共猜了{0}次 用时{1}秒",
                    GetCount(), label2!.Text), "恭喜!");  //显示游戏信息
                button1!.Enabled = true;                   //启用开始按钮
            }
        }
        /// <summary>
        /// 用于代替thread1!.Abort();
        /// SYSLIB0006:不支持 Thread.Abort
        /// 替代方案我没有深究是否有效,仅提供指明的解决方向
        /// </summary>
        static void Thread_Abort(CancellationToken cancellationToken)
        {         
                // If the CancellationToken is marked as "needs to cancel",
                // this will throw the appropriate exception.
                cancellationToken.ThrowIfCancellationRequested();
        }
    }
}

三、生成效果

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

tp5+workman(GatewayWorker) 安装及使用

一、安装thinkphp5 1、宝塔删除php禁用函数putenv、pcntl_signal_dispatch、pcntl_wai、pcntl_signal、pcntl_alarm、pcntl_fork&#xff0c;执行安装命令。 composer create-project topthink/think5.0.* tp5 --prefer-dist 2、配置好站点之后&#xff0c;浏览器打开访问成…

Qt菜单工具栏和状态栏

QMenuBar 接口介绍 QAction 定义&#xff1a;QAction 是一个独立于具体界面元素的抽象动作表示。它封装了一个用户界面动作&#xff08;比如点击命令&#xff09;&#xff0c;通常与一个菜单项、工具栏按钮或快捷键相关联。用途&#xff1a;你可以将 QAction 视为一个可执行的…

解决Android Studio的adb命令行报错Permission denied问题-建议收藏备用!

目录 前言 一、报错信息 二、常见解决方法 三、最简单的解决方法 四、更多资源 前言 随着移动设备的普及&#xff0c;Android操作系统成为了全球最主要的移动设备操作系统之一。在开发和调试Android应用程序时&#xff0c;我们常常需要使用adb&#xff08;Android Debug B…

Resnet BatchNormalization 迁移学习

时间&#xff1a;2015 网络中的亮点&#xff1a; 超深的网络结构&#xff08;突破1000层&#xff09;提出residual模块使用Batch Normalization加速训练&#xff08;丢弃dropout&#xff09; 层数越深效果越好&#xff1f; 是什么样的原因导致更深的网络导致的训练效果更差呢…

云计算:OpenStack 分布式架构部署(单控制节点与多计算节点)

目录 一、实验 1.环境 2. 计算服务安装(计算节点2) 3. 网络服务安装(计算节点2) 一、实验 1.环境 (1) 主机 表1 主机 主机架构IP备注controller控制节点192.168.204.210已部署compute01计算节点1192.168.204.211 已部署compute02计算节点2192.168.204.212 &#xff08;…

如何下载Sentinel-1数据

Sentinel-1是欧洲空间局&#xff08;ESA&#xff09;的一组地球观测卫星&#xff0c;属于Copernicus计划的一部分。该计划旨在为全球环境监测提供数据&#xff0c;并支持应对气候变化、自然灾害和人类活动的挑战。Sentinel-1卫星的主要任务是提供全天候、全时段、高分辨率的合成…

C#-CSC编译环境搭建

一.Microsoft .NET Framework 确保系统中安装Microsoft .NET Framework相关版本下载 .NET Framework 4.7 | 免费官方下载 (microsoft.com)https://dotnet.microsoft.com/zh-cn/download/dotnet-framework/net47 二.编译环境搭建 已经集成编译工具csc.exe,归档至gitcode,实现us…

5G随身WiFi避坑,5G随身WiFi口碑推荐,5G随身WiFi避雷,5G随身WiFi好用吗?

第一、切忌盲目入坑&#xff0c;目前市面上的主流随身 WiFi都是4G网络&#xff0c;不支持5G&#xff0c;当一些只卖几十块的随身WiFi&#xff0c;商家告诉你是5G随身WiFi的时候&#xff0c;直接拉黑。随身WiFi芯片都上百了&#xff0c;设备才几十块&#xff0c;怎么可能&#x…

浅聊配置化-要不要实现动态表单

1、配置化的原则 配置化是一种抽象&#xff0c;把事物分成2类&#xff1a;不变的&#xff0c;可变的。 如果事物都是可变的&#xff0c;是无法实现配置化的。 配置化的根本在于找到不变的事物&#xff0c;基于不变的事物进行可变事物的配置。 所以&#xff0c;认为一切皆可…

老子的《道德经》透露,不努力反而更成功

人类生而自由&#xff0c;但到处都是枷锁。 永远不要怀疑经过慎思且足够投入的一小群人能否改变这个世界。事实上&#xff0c;只有他们才办得到。 优美灵魂的两个发展方向&#xff1a;崇拜道德的天才&#xff0c;对别人实行道德的判断。 一、道 《道德经》开始的名字是《老子…

数据结构:第7章:查找(复习)

目录 顺序查找&#xff1a; 折半查找&#xff1a; 二叉排序树&#xff1a; 4. (程序题) 平衡二叉树&#xff1a; 顺序查找&#xff1a; ASL 折半查找&#xff1a; 这里 j 表示 二叉查找树的第 j 层 二叉排序树&#xff1a; 二叉排序树&#xff08;Binary Search Tree&…

零知识证明(zk-SNARK)- groth16(一)

全称为 Zero-Knowledge Succinct Non-Interactive Argument of Knowledge&#xff0c;简洁非交互式零知识证明&#xff0c;简洁性使得运行该协议时&#xff0c;即便 statement 非常大&#xff0c;它的 proof 大小也仅有几百个bytes&#xff0c;并且验证一个 proof 的时间可以达…

2023年年度总结,一个小白的CSDN涨粉历程

前言 滚滚长江东逝水&#xff0c;一去不复返。 转眼间已到2024年节点&#xff0c;时间如滚滚长江水向东奔流不息&#xff0c;在长江消失之前&#xff0c;都不会停歇&#xff0c;也不会回头。人亦如此&#xff0c;不管是生活还是学习&#xff0c;都是不断往前走的过程&#xff…

数据中台的数据处理及应用说明

科技飞速发展的时代&#xff0c;企业信息化建设会越来越完善&#xff0c;越来越体系化&#xff0c;当今数据时代背景下更加强调、重视数据的价值&#xff0c;以数据说话&#xff0c;通过数据为企业提升渠道转化率、改善企业产品、实现精准运营&#xff0c;为企业打造自助模式的…

[BUG]Datax写入数据到psql报不能序列化特殊字符

1.问题描述 Datax从mongodb写入数据到psql报错如下 org.postgresql.util.PSQLException: ERROR: invalid bytesequence for encoding "UTF8": 0x002.原因分析 此为psql独有的错误&#xff0c;不能对特殊字符’/u0000’,进行序列化&#xff0c;需要将此特殊字符替…

GCP 创建1个windows vm 并连接

有时需要临时使用1台windows 的机器 创建windows vm 既然是临时 直接用gcloud command gcloud compute instances create instance-windows \--zoneeurope-west2-c \--machine-typen2d-standard-4 \--boot-disk-size100GB \--image-projectwindows-cloud \--imagewindows-se…

力扣回溯算法-电话号码的字母组合

力扣第17题&#xff0c;电话号码的字母组合 题目 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 .电话号码的字母组合 示例: 输入&#xff1a;“2…

【动态规划】【字符串】C++算法:正则表达式匹配

作者推荐 视频算法专题 涉及知识点 动态规划 字符串 LeetCode10:正则表达式匹配 给你一个字符串 s 和一个字符规律 p&#xff0c;请你来实现一个支持 ‘.’ 和 ‘’ 的正则表达式匹配。 ‘.’ 匹配任意单个字符 ’ 匹配零个或多个前面的那一个元素 所谓匹配&#xff0c;是…

ORACLE Primavera Unifier v23.12 最新虚拟机(VM)分享下载

引言 根据上周的计划&#xff0c;我近日简单制作了一个基于ORACLE Primavera Unifier 最新版23.12的虚拟机演示环境&#xff0c;里面包括了unifier的全套系统服务 此虚拟系统环境仅用于演示、培训和测试目的。如要在生产环境中使用此虚拟机&#xff0c;请您与Oracle 销售代表联…

使用setoolkit制作钓鱼网站并结合dvwa靶场储存型XSS漏洞利用

setoolkit是一款kali自带的工具 使用命令启动 setoolkit 1) Social-Engineering Attacks 1&#xff09; 社会工程攻击 2) Penetration Testing (Fast-Track) 2&#xff09; 渗透测试&#xff08;快速通道&#xff09; 3) Third Party Module…