本文以一个线程实时动态的改变主线程上面的label的text值为例子
步骤
- 新建项目和添加事件
- 核心代码书写
新建项目和添加事件
首先在窗口上面添加一个label两个按钮(分别用来开始子线程和终止子线程)
然后为两个按钮添加click事件
核心代码的书写
在代码区的窗口类下面添加一个BackgroundWorker控件(注意添加命名空间using System.ComponentModel;)
BackgroundWorker可以当它就是一个子线程
在button2的click事件 配置子线程(包括子线程执行的函数等)
为子线程添加 工作函数BackWorker_DoWork和能够访问主线程的BackWorker_ProgressChanged函数
//点击button2 配置子线程(包括子线程执行的函数等)
private void button2_Click(object sender, EventArgs e)
{
//为子线程添加需要执行的函数
backWorker.DoWork += BackWorker_DoWork;
//开始执行函数 并且传入一个参数 100
backWorker.RunWorkerAsync(100);
//指示是否在执行过程中可以 调用ProgressChanged函数
backWorker.WorkerReportsProgress = true;
//添加需要执行的ProgressChanged函数(该函数是子线程控制主线程的关键函数,我们不能在DoWork函数中访问其他主线程的控件但是在ProgressChanged函数中可以)
backWorker.ProgressChanged += BackWorker_ProgressChanged;
//指示子线程是否可以被终止
backWorker.WorkerSupportsCancellation = true;
}
然后再为任务添加内容
内容是 循环计算1加到100的求和 将 每次循环 求和的结果先发送到BackWorker_ProgressChanged函数中
因为我们不能在BackWorker_DoWork这个工作函数中访问主线程的控件,只能在BackWorker_ProgressChanged函数
(注意Thread类需要用到的命名空间是using System.Threading;)
//子线程需要执行的函数
private void BackWorker_DoWork(object sender, DoWorkEventArgs e)
{
//获取执行这个函数的线程
BackgroundWorker bgWorker = sender as BackgroundWorker;
//用end获取传进来的参数
int end = 0;
if (e.Argument != null)
{
end = (int)e.Argument;
}
//函数的注意作用是循环执行下面的计算操作
int sum = 0;
for (int i = 0; i <= end; i++)
{
//计算操作
sum += i;
string text = "现在的计算结果是: " + sum.ToString();
//调用BackWorker_ProgressChanged函数(该函数可以访问主线程的控件,实现线程之间的访问主要靠它)
//并且返回本次循环的计算结果到BackWorker_ProgressChanged函数
bgWorker.ReportProgress(i, text);
//子线程暂停600毫秒,避免过快计算,看不出效果
Thread.Sleep(600);
//每次循环都检测 用户是否点击了button1按钮也就是终止子线程的按钮
//当BackgroundWorker类调用了CancelAsync()方法就会使得BackgroundWorker类的CancellationPending值为true
if (bgWorker.CancellationPending == true)
{
//正式终止本线程
e.Cancel = true;
break;
}
}
}
然后在BackWorker_ProgressChanged函数中将发送过来的结果赋值到label控件上实现对主线程的访问
private void BackWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//获取每次循环的计算结果
string text = e.UserState.ToString();
this.label1.Text = text;
}
最后在button1的click函数中添加终止子线程的方法
//点击button1 提出终止子线程申请
private void button1_Click(object sender, EventArgs e)
{
//向backWorker线程提出 要终止backWorker线程,但并非正式终止该线程
//调用的下面的方法以后 该线程的CancellationPending属性的值 将等于 true 以此来知道提出了终止申请
backWorker.CancelAsync();
//只有在提出终止申请以后执行 e.Cancel = true; 语句子线程才能真正终止
}
下面是所有代码的展示
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace progressBar_text
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//新建一个BackgroundWorker实例(新建一个子线程backWorker)
BackgroundWorker backWorker = new BackgroundWorker();
//点击button2 配置子线程(包括子线程执行的函数等)
private void button2_Click(object sender, EventArgs e)
{
//为子线程添加需要执行的函数
backWorker.DoWork += BackWorker_DoWork;
//开始执行函数 并且传入一个参数 100
backWorker.RunWorkerAsync(100);
//指示是否在执行过程中可以 调用ProgressChanged函数
backWorker.WorkerReportsProgress = true;
//添加需要执行的ProgressChanged函数(该函数是子线程控制主线程的关键函数,我们不能在DoWork函数中访问其他主线程的控件但是在ProgressChanged函数中可以)
backWorker.ProgressChanged += BackWorker_ProgressChanged;
//指示子线程是否可以被终止
backWorker.WorkerSupportsCancellation = true;
}
//点击button1 提出终止子线程申请
private void button1_Click(object sender, EventArgs e)
{
//向backWorker线程提出 要终止backWorker线程,但并非正式终止该线程
//调用的下面的方法以后 该线程的CancellationPending属性的值 将等于 true 以此来知道提出了终止申请
backWorker.CancelAsync();
//只有在提出终止申请以后执行 e.Cancel = true; 语句子线程才能真正终止
}
//子线程需要执行的函数
private void BackWorker_DoWork(object sender, DoWorkEventArgs e)
{
//获取执行这个函数的线程
BackgroundWorker bgWorker = sender as BackgroundWorker;
//用end获取传进来的参数
int end = 0;
if (e.Argument != null)
{
end = (int)e.Argument;
}
//函数的注意作用是循环执行下面的计算操作
int sum = 0;
for (int i = 0; i <= end; i++)
{
//计算操作
sum += i;
string text = "现在的计算结果是: " + sum.ToString();
//执行ReportProgress函数(该函数可以访问主线程的控件,实现线程之间的访问主要靠它)
//并且返回本次循环的计算结果
bgWorker.ReportProgress(i, text);
//子线程暂停600毫秒,避免过快计算,看不出效果
Thread.Sleep(600);
//每次循环都检测 用户是否点击了button1按钮也就是终止子线程的按钮
//当BackgroundWorker类调用了CancelAsync()方法就会使得BackgroundWorker类的CancellationPending值为true
if (bgWorker.CancellationPending == true)
{
//正式终止本线程
e.Cancel = true;
break;
}
}
}
private void BackWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//获取每次循环的计算结果
string text = e.UserState.ToString();
this.label1.Text = text;
}
}
}
参考文献
https://www.cnblogs.com/sparkdev/p/5906272.html