C#_多线程编程入门

news2025/1/14 0:42:50

字面理解:多个线程同时工作的过程。

案例①   单线程

        #region ① 单线程做菜
        /// <summary>
        /// ① 单线程做菜:执行任务时,什么操作都动不了.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SingleThread_Click(object sender, EventArgs e)
        {
            Thread.Sleep(3000);
            MessageBox.Show("素菜做好了","友情提示");
            Thread.Sleep(3000);
            MessageBox.Show("荤菜做好了", "友情提示");
        }
        #endregion

单线程_效果

做菜(先做完素菜,再做荤菜)时,当前窗口无法操作(移动、拉伸等)。

案例②  多线程

        #region ② 多线程做菜
        /// <summary>
        /// ② 多线程做菜:执行任务时,可以对其他功能操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void multiThreading_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(() =>
            {
                Thread.Sleep(3000);
                MessageBox.Show("素菜做好了", "友情提示");
                Thread.Sleep(5000);
                MessageBox.Show("荤菜做好了", "友情提示");
            });
            thread.Start();
        }
        #endregion

多线程_效果

做菜(先做完素菜,再做荤菜)时,当前窗口进可以行操作(移动、拉伸等)。

案例③  任务

        #region ③ 任务做菜
        /// <summary>
        /// ③ 任务做菜:执行任务时,可以对其他功能操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnTask_Click(object sender, EventArgs e)
        {
            Task.Run(() =>
            {
                Thread.Sleep(3000);
                MessageBox.Show("素菜做好了", "友情提示");
                Thread.Sleep(5000);
                MessageBox.Show("荤菜做好了", "友情提示");
            });
        }
        #endregion

任务_效果

做菜(先做完素菜,再做荤菜)时,当前窗口进可以行操作(移动、拉伸等)。

案例④  同步

        #region ④ 同步做菜
        /// <summary>
        /// ④ 同步做菜:同时运行任务
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSynchornization_Click(object sender, EventArgs e)
        {
            Task.Run(() =>
            {
                Thread.Sleep(3000);
                MessageBox.Show("素菜做好了", "友情提示");
            });
            Task.Run(() =>
            {
                Thread.Sleep(5000);
                MessageBox.Show("荤菜做好了", "友情提示");
            });
        }
        #endregion

同步_效果

素菜和荤菜可以同时做,当前窗口进可以行操作(移动、拉伸等)。

案例⑤  异步

        #region 做好菜了,来吃饭(异步)
        /// <summary>
        /// ⑤ 做好菜了,来吃饭(异步):等待任务完成后,才继续往下执行.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void btnAsync_Click(object sender, EventArgs e)
        {
            await Task.Run(() =>
            {
                Thread.Sleep(3000);
                MessageBox.Show("素菜做好了", "友情提示");
                Thread.Sleep(5000);
                MessageBox.Show("荤菜做好了", "友情提示");
            });
            MessageBox.Show("做好菜了,来吃饭", "友情提示");
        }
        #endregion

异步_效果

等待完成这个任务完成后,才执行“来吃饭”;UI和逻辑不在同个线程。

案例⑥  并行

        #region ⑥ 做好菜了,来吃饭(并行)
        /// <summary>
        /// ⑥ 做好菜了,来吃饭(并行):异步完成任务后,才继续往下执行.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnParallel_Click(object sender, EventArgs e)
        {
            //1. 创建泛型为Task的集合对象
            List<Task> Ltasks = new List<Task>();
            //2. 添加任务
            Ltasks.Add(Task.Run(() =>
            {
                Thread.Sleep(3000);
                MessageBox.Show("素菜做好了", "友情提示");
            }));
            Ltasks.Add(Task.Run(() =>
            {
                Thread.Sleep(5000);
                MessageBox.Show("荤菜做好了", "友情提示");
            }));
            //3. 将所有Task对象完成后,创建新的异步延续任务
            Task.WhenAll(Ltasks).ContinueWith(ts =>
            {
                MessageBox.Show("做好菜了,来吃饭", "友情提示");
            });

        }
        #endregion

并行_效果

等待完成所有任务完成后,才执行“来吃饭”;UI和逻辑不在同个线程。

案例⑦  使用线程组件跨线程传输信息和状态

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MyWorkBook.MyTest
{
    public partial class ThreadForm : Form
    {
        public ThreadForm()
        {
            InitializeComponent();
            backgroundWorker1.WorkerReportsProgress = true;//是否支持发送进度报告。
            backgroundWorker1.WorkerSupportsCancellation = true;//是否支持取消异步操作。
        }

        /// <summary>
        /// 线程控件触发事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            //通过Object对象可以获取线程组件;以下代码会另起一个线程,而不是在UI线程中运行。
            BackgroundWorker worker = sender as BackgroundWorker;

            for(int i = 1; i <= 100; i++)
            {
                if(worker.CancellationPending == true)//应用程序已请求取消后台操作
                {
                    e.Cancel = true;//取消事件--更改运行返回状态,并不能取消停止
                    break;
                }
                else
                {
                    Thread.Sleep(50);//实际应用编码时,该程式是为工作代码。
                    worker.ReportProgress(i);//当线程进度发给改变时,触发线程组件发生改变后触发事件(backgroundWorker1_ProgressChanged)并传参。
/*发送*/
                    var data = Tuple.Create("Hallen",true,27);//创建元数组数据。
                    worker.ReportProgress(i, data);

                }
            }
            e.Result = e.Argument;//根据操作异步参数给操作异步结果赋值---应用于线程完成(失败/成功)后触发事件。
        }

        /// <summary>
        /// 线程组件发生改变后触发事件---在创建BackgroundWorker线程上执行,是异步调用,和引发事件代码是在不同线程。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;//将异步任务进度百分比赋值给进度条
            resultLabel.Text = (e.ProgressPercentage.ToString() + "%");//将异步任务进度百分比赋值给标签组件显示进度数值

/*接收---跨线程接收信息和状态*/

            if(e.UserState != null)
            {
                Tuple<string, bool, int> data = (Tuple<string, bool, int>)e.UserState;
                lbl_state.Text = $"姓名{data.Item1},性别{data.Item2},年龄{data.Item3}";
            }            
        }

        /// <summary>
        /// 启动按钮触发事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            if(backgroundWorker1.IsBusy != true)//判断异步操作不在进行
            {
                backgroundWorker1.RunWorkerAsync("你是坏淫吗?对,你是的。");//开始异步操作
            }
        }

        /// <summary>
        /// 取消按钮触发事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            if(backgroundWorker1.WorkerSupportsCancellation == true)//判断支持异步取消操作
            {
                backgroundWorker1.CancelAsync();//请求取消挂起后台操作
            }
        }

        /// <summary>
        /// 线程完成(失败/成功)后触发事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if(e.Cancelled == true)//后台操作已取消
            {
                resultLabel.Text = "Canceled";
            }else if(e.Error != null)//异步操作期间发生错误
            {
                resultLabel.Text = "Error:"+ e.Error.Message;
            }
            else//后台操作成功
            {
                resultLabel.Text = "Done! Result = "+ e.Result;
            }
        }
    }
}

 运行效果

 

案例⑧  使用Invoke跨线程传输信息和状态

        #region ②串口数据接收事件
        /// <summary>
        /// ②串口数据接收事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)//串口数据接收事件
        {
            Invoke((EventHandler)delegate  //在UI线程上执行委托,而以下代码是委托需求。
            {

                Thread.Sleep(20);

                if (radioButton4.Checked)//接收模式为字符模式
                {
                    string str1 = serialPort1.ReadExisting();//字符串模式读
                    textBox1.AppendText(str1 + "\r\n");
                }//添加内容

                if (radioButton2.Checked)//接收模式为数值模式
                {
                    byte data = (byte)serialPort1.ReadByte();//此处需要强制类型转换,将int类型数据转换byte类型数据,不必考虑是否丢失数据
                    string str2 = Convert.ToString(data, 16).ToUpper();//转换为大写十六进制字符串
                    textBox1.AppendText("0x" + (str2.Length == 1 ? "0" + str2 : str2) + "\r\n");
                }

                if (radioButton6.Checked)//接收模式为中文模式

                {
                    //在c#中,如果是通过串口要给下位机发送中文编码或给其他软件(如串口调试助手),则最好采用unicode编码
                    //System.Text.UnicodeEcoding unic= new System.Text.UnicodeEcoding ();
                    //Byte[] writeBytes = unic.GetBytes("你好世界");---接收
                    //serialPort.Write(writeBytes, 0, writeBytes.Length);--发送

                    UTF8Encoding utf8 = new UTF8Encoding();//创建UTF8编码对象
                    Byte[] readBytes = new Byte[serialPort1.BytesToRead];//获取缓冲区数据的字节数
                    serialPort1.Read(readBytes, 0, readBytes.Length);
                    String decodedString = utf8.GetString(readBytes);//UTF8解码后转换为string类型
                    textBox1.AppendText(decodedString + "\r\n");
                }
            });
        }
        #endregion

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

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

相关文章

只需半分钟,ARMS 帮你配置出“高质量”告警

作者&#xff1a;图杨 背景 某位资深运维工程师A&#xff1a;“一天不收个几十条告警&#xff0c;我都觉得心里不踏实” 。运维工程师B&#xff1a;“我那几个告警天天告&#xff0c;我的应用一点问题都没有&#xff0c;但是我又不敢关”。运维工程师C&#xff1a;“我每天都…

安果天气预报 产品介绍

软件介绍版本号 2.0.5 安果天气预报&#xff1a;全世界覆盖&#xff0c;中国定制 想要查找北京、上海、纽约、东京还是巴黎的天气&#xff1f;一款简约的天气预 报应用为你呈现。专注于为用户提供纯净的天气体验&#xff0c;我们不发送任何打扰的通知。包含空气质量、能见度、…

使用Python搭建服务器公网展示本地电脑文件

文章目录 1.前言2.本地http服务器搭建2.1.Python的安装和设置2.2.Python服务器设置和测试 3.cpolar的安装和注册3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 1.前言 Python作为热度比较高的编程语言&#xff0c;其语法简单且语句清晰&#xff0c;而且python有…

搜索树基础:二叉搜索树(详解特性用途,图解实现过程)

二叉搜索树 二叉搜索树的特性二叉搜索树的主要用途二叉搜索树的基本操作1、二叉搜索树的查找2、二叉搜索树的插入3、二叉搜索树的删除&#xff08;难点&#xff09;&#xff08;1&#xff09;找到待删结点&#xff08;2&#xff09;分情况删除 二叉搜索树的特性 二叉搜索树又称…

如何高效沟通避免沟通冲突 ?2大沟通漏斗模型

“昨天&#xff0c;我不是说这个Bug了&#xff1f;”“没有啊&#xff0c;你啥时候说的&#xff1f;”项目组成员沟通效率不高&#xff0c;往往造成沟通误解、争论不休&#xff0c;甚至出现沟通冲突&#xff0c;影响项目进度。 那么该如何提高沟通效率&#xff0c;避免不必要的…

Fmoc-D-Ser(Ac4-L-Manα)-OH主要采用的是Fmoc合成法,Fmoc合成法是以Fmoc为α-氨基的保护基

Fmoc-D-Ser(Ac4-L-Manα)-OH主要采用的是Fmoc合成法。Fmoc合成法是以Fmoc为α-氨基的保护基&#xff0c;配合侧链保护的苄醇类&#xff0c;完成多肽合成。 在西安凯新生物科技有限公司的Fmoc合成法的实施过程中&#xff0c;首先将一个Fmoc&#xff0d;氨基酸衍生物共价交联到树…

老师们如何轻松制作学生分班查询系统

当暑假即将结束&#xff0c;老师们面临着许多事务&#xff0c;其中一个重要的任务是制作分班信息查询系统。这个工具对于老师们来说非常重要&#xff0c;因为它可以提供给家长和学生们方便快捷的查询服务。 分班信息查询系统可以让家长和学生们通过系统查询自己所在的班级、同班…

如何快捷发布学生分班情况

暑假即将结束&#xff0c;老师们面临着许多事务&#xff0c;其中一个重要的任务是制作分班信息查询系统。这个工具对于老师们来说非常重要&#xff0c;因为它可以提供给家长和学生们方便快捷的查询服务。 分班信息查询系统可以让家长和学生们通过系统查询自己所在的班级、同班同…

MySQL每日一练--校园教务系统

一丶数据库名称&#xff1a;SchoolDB 二丶数据库表信息&#xff1a;角色信息表 表名&#xff1a; t_role 主键&#xff1a; r_id 序号 字段名称 字段说明 类别 位数 属性 备注 1 r_id 角色编号 int 主键 自动增长 2 r_name_EN 角色名&#xff08;英文…

CPU内部单总线方式——例题分析

指令&#xff1a;ADD &#xff08;R0&#xff09;,R1 &#xff08;R0&#xff09; 目的操作数 &#xff08;R0&#xff09;说明R0中存放的是目的操作数的地址&#xff0c;则需要一次间接寻址 R1 源操作数 直接存在了R1寄存器中 最后&#xff08;R0&#xff09;存入R0所指向的存…

能源行业配电柜监控,这也太智能了!

在能源行业中&#xff0c;配电柜作为能量传输和控制的关键枢纽&#xff0c;其稳定运行直接关系到供电系统的可靠性和安全性。随着技术的不断进步&#xff0c;配电柜监控系统的发展为能源管理带来了全新的可能性。 配电柜监控系统的引入为能源行业带来了更高的智能化水平和管理效…

成集云 | 旺店通多包裹数据同步钉钉 | 解决方案

源系统成集云目标系统 方案介绍 随着品牌电商兴起&#xff0c;线上线下开始逐渐融为一体&#xff0c;成集云以旺店通ERP系统为例&#xff0c;通过成集云-旺店通连接器&#xff0c;将旺店通ERP系统多包裹数据同步至钉钉实现数据互通&#xff0c;帮助企业解决了电商发货存在的错…

面向对象知识点

一.Static 1.static修饰成员变量 被static修饰的成员变量&#xff0c;也叫做类变量&#xff0c;与类一同加载&#xff0c;只加载一次&#xff0c;被当前类的所有对象共享&#xff0c;只有一个 可以通过类名.属性的方法调用&#xff0c;也可以使用对象.属性的方式调用 应用场…

备份集中的数据库备份与现有的数据库不同?

数据已经成为公司的主要资产,特别是对于企业来说&#xff0c;数据库中存储的信息通常是其业务运营的核心。 因此&#xff0c;确保数据库的安全性和完整性至关重要。这导致数据库备份成为企业信息管理的重要组成部分。本文将详细介绍备份密集数据库备份的必要性&#xff0c;以及…

【python】Leetcode(primer-pointer)

文章目录 26. 删除有序数组中的重复项&#xff08;快慢指针&#xff09;88. 合并两个有序数组&#xff08;双指针&#xff09;167. 两数之和 II - 输入有序数组&#xff08;双指针&#xff09; 更多 leetcode 题解可参考&#xff1a;【Programming】 26. 删除有序数组中的重复项…

【linux内核】DP83867添加GMII模式支持

文章目录 修改方案前期知识为什么这么修改&#xff1f;通用寄存器 修改方案 linux 4.0内核下/drivers/net/phy/dp83867.c phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, val);} if (phydev->interface PHY_INTERFACE_MODE_GMII){val phy_read_mmd(phydev, DP838…

CLIP(Contrastive Language-Image Pre-training)

《Learning Transferable Visual Models From Natural Language Supervision》 从自然语言监督中学习可迁移的视觉模型 贡献:利用自然语言信号监督,打破了固定类别的范式。 方法简单,效果好。从文本中得到监督信号,引导视觉分类的任务。 它是一个 zero-shot 的视觉分类…

深度研究:ASEMI快恢复二极管APT60DQ20BG

编辑-Z 在众多电子元件中&#xff0c;快恢复二极管APT60DQ20BG因其独特属性和广泛应用&#xff0c;吸引了广大电子爱好者和工程师的目光。本文将为您进行全面、深入的剖析。 首先&#xff0c;我们需要理解APT60DQ20BG是什么。APT60DQ20BG是一种快恢复二极管。二极管作为一个电…

【MySQL系列】Select语句单表查询详解(一)

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

搭建AI智能问答的这些前期工作可不要忘了

在搭建AI智能问答之前&#xff0c;我们需要做好相应的前期准备工作&#xff0c;不能盲目地去搭建模型。这样很容易导致我们模型后续的不完整性。所以looklook今天就基于搭建AI智能问答最基础的思路&#xff0c;带领大家一起去理顺一下我们需要做什么前期工作才能保证AI智能问答…