多线程+代理操作控件

本文介绍了一个使用线程进行后台计算,并实时更新多个窗体控件的例子。通过线程进行后台运算的同时,利用委托确保UI线程的控件更新,避免界面冻结。文章详细展示了如何在不同窗体间同步进度条和文本框的内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

试了一下BackgoundWorker,感觉用起来很不顺手,习惯了使用线程。

目标:后台计算时,在textbox里显示计算的步数,在两个progressbar里显示进度,一个progressbar在本窗体,一个在另一个窗体里。

代码:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace 异步代理刷新控件 { public partial class Form1 : Form { //使用线程或者异步委托调用,没有区别。 private Thread thread; private delegate void InvokeDelegate(); private delegate void UpdateProgressBar(int i); private InvokeDelegate invokeDelegate; private UpdateProgressBar deleUpdateProgressBar; ProgressForm pf; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //初始化线程 this.thread = new Thread(new ThreadStart(this.FunTest)); //初始化两个代理实例 this.invokeDelegate = new InvokeDelegate(this.FunTest); this.deleUpdateProgressBar = new UpdateProgressBar(this.SetProgress); pf = new ProgressForm(this.thread); } private void FunTest() { for (int i = 1; i < 100001; i++) { //搜索控件句柄,判断控件是否生成,不生成则返回false,此时就不能调用begininvoke方法了 //另外,如果对if内部语句的调用发生在同一线程(即UI线程或主线程),则InvokeRequired将返回false; if (this.progressBar1.InvokeRequired)//异步 { //运算(往往时后台的大量运算,不涉及控件) this.Calculation(i); //操作控件。注意参数,第二个参数是deleUpdateProgressBar所绑定的函数的所有参数 this.progressBar1.BeginInvoke(this.deleUpdateProgressBar, new object[] { i }); //一定注意,Sleep的动作一定不能放在SetTextBoxValue()方法中,因为控件的BeginInvoke()会将SetTextBoxValue()方法 //封送至后台线程,这就变成了在后台线程中让主线程Sleep300ms的时间,而不是让后台线程Sleep300ms了。 Thread.Sleep(1); } else//同步 { this.SetProgress(i); Thread.Sleep(1); } } } private void Calculation(int i) { int j = i * i;//用此代表一个大量的运算 } private void SetProgress( int i)//参数pb没有必要,可以直接调用控件,无需作为参数 { pf.progressBar1.Value = i; this.progressBar1.Value = i; this.textBox1.Text = i.ToString(); if (i == 100000) { MessageBox.Show("计算完成"); } } private void button1_Click(object sender, EventArgs e) { //this.invokeDelegate.BeginInvoke(null, null);//异步调用 //this.FunTest();//直接同步调用 //this.invokeDelegate();//同步委托调用 if (!pf.IsDisposed)//注意不要使用null判断,对象释放并不意味pf等于null { pf.Show(); } else { pf = new ProgressForm(this.thread); pf.Show(); } //线程调用 if (this.thread.IsAlive) { if (this.thread.ThreadState == ThreadState.Unstarted)//根据状态判断是否启动 { this.thread.Start(); } } else { this.thread = new Thread(new ThreadStart(this.FunTest)); this.thread.Start(); } } //这个函数代表,在做运算时,判断其他动作是否可操作 private void button2_Click(object sender, EventArgs e) { lock (this.progressBar1)//应先锁定 { if (this.progressBar1.Value < this.progressBar1.Maximum) { MessageBox.Show("正在运行,禁止介入!"); } else { MessageBox.Show("计算完毕,可以介入!"); } } } private void button3_Click(object sender, EventArgs e) { //函数过时 this.thread.Suspend(); } private void button4_Click(object sender, EventArgs e) { if (this.thread.ThreadState == ThreadState.Suspended) { this.thread.Resume(); } } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { this.thread.Abort();//窗体关闭时,必须销毁线程,如果在线程运行时关闭窗体,该线程仍在计算中 } } }

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace 异步代理刷新控件 { public partial class ProgressForm : Form { public ProgressForm() { InitializeComponent(); } public Thread thread; public ProgressForm(Thread t) { InitializeComponent(); this.thread = t; } } }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值