C# 使用委托实现多线程调用窗体的四种方式
1、方法一:使用线程
功能描述:在用c#做WinFrom开发的过程中。我们经常需要用到进度条(ProgressBar)用于显示进度信息。这时候我们可能就需要用到多线程,如果不采用多线程控制进度条,窗口很容易假死(无法适时看到进度信息)。下面我就简单结合一个我写的例子给大家做一个介绍。
第一步:设计界面,注意需要引用 using System.Threading;

private delegate void SetPos(int ipos,string vinfo);//代理
第三步:进度条值更新函数(参数必须跟声明的代理参数一样)
private void SetTextMesssage(int ipos,string vinfo)
{
if (this.InvokeRequired)
{
SetPos setpos = new SetPos(SetTextMesssage);
this.Invoke(setpos, new object[] { ipos,vinfo });
}
else
{
this.label1.Text = ipos.ToString() + "/1000";
this.progressBar1.Value = Convert.ToInt32(ipos);
this.textBox1.AppendText(vinfo);
}
}
第四步:函数实现
private void button1_Click(object sender, EventArgs e)
{
Thread fThread = new Thread(new ThreadStart(SleepT));
fThread.Start();
}
第五步:新的线程执行函数:
private void SleepT()
{
for (int i = 0; i < 500; i++)
{
System.Threading.Thread.Sleep(10);
SetTextMesssage(100*i/500,i.ToString()+"\r\n");
}
}
程序运行效果图:


控件名称:
button1;backgroundWorker1;
对backgroundWorker1控件,属性设置:

第二步:主页面后台代码:
using System.Threading;//引用空间名称
private void button1_Click(object sender, EventArgs e)
{
this.backgroundWorker1.RunWorkerAsync(); // 运行 backgroundWorker 组件
ProcessForm form = new ProcessForm(this.backgroundWorker1);// 显示进度条窗体
form.ShowDialog(this);
form.Close();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
}
else
{
}
}
//你可以在这个方法内,实现你的调用,方法等。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
worker.ReportProgress(i);
if (worker.CancellationPending) // 如果用户取消则跳出处理数据代码
{
e.Cancel = true;
break;
}
}
}
分别为button控件和backgroundWorker1控件选好事件。
第三步:设置子窗体(及显示进度条的窗体):

private BackgroundWorker backgroundWorker1; //ProcessForm 窗体事件(进度条窗体)
public ProcessForm(BackgroundWorker backgroundWorker1)
{
InitializeComponent();
this.backgroundWorker1 = backgroundWorker1;
this.backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
this.backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
}
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//this.Close();//执行完之后,直接关闭页面
}
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar1.Value = e.ProgressPercentage;
}
private void button1_Click(object sender, EventArgs e)
{
this.backgroundWorker1.CancelAsync();
this.button1.Enabled = false;
this.Close();
}
}
只为button选好事件
执行效果为:

=================================================================================================
3、第三种方法:
功能描述:在处理大量数据的时候,有时候方法的执行需要一定的时间,这时候往往会造成页面或程序的“假死”状态,给用户的体验度也不是很好。为了避免出现“假死”提高用户的体验度,在这里为这类型的方法加了一个进度条和一个文本框,进度条用于显示程序处理的进度,文本框用于显示在处理过程中,给与的提示。本方法主要使用了控件:backgroundWorker1;说明:本方法与上面的方法(方法二)基本类型,主要是设计和代码进行了一些修改。
第一步:主窗体设计:
控件名称:
button1;backgroundWorker1;
对backgroundWorker1控件,属性设置:
第二步:主窗体 后台代码:
private void button1_Click(object sender, EventArgs e)
{
this.backgroundWorker1.RunWorkerAsync(); // 运行 backgroundWorker 组件
ProcessForm form = new ProcessForm(this.backgroundWorker1);// 显示进度条窗体
form.ShowDialog(this);
form.Close();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
}
else
{
}
}
//你可以在这个方法内,实现你的调用,方法等。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
worker.ReportProgress(i, i.ToString() + " 你好!\r\n"); //注意:这里向子窗体返回信息值,这里是两个值,一个用于进度条,一个用于文本框的。
if (worker.CancellationPending) // 如果用户取消则跳出处理数据代码
{
e.Cancel = true;
break;
}
}
}
第三步:设置子窗体(及显示进度条的窗体):

控件:
progressBar1;textBox1;button1
第四步:子窗体后台代码:
private BackgroundWorker backgroundWorker1; //ProcessForm 窗体事件(进度条窗体)
public ProcessForm(BackgroundWorker backgroundWorker1)
{
InitializeComponent();
this.backgroundWorker1 = backgroundWorker1;
this.backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
this.backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
}
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//this.Close();//执行完之后,直接关闭页面
}
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar1.Value = e.ProgressPercentage;
this.textBox1.AppendText(e.UserState.ToString());//主窗体传过来的值,通过e.UserState.ToString()来接受
}
private void button1_Click(object sender, EventArgs e)
{
this.backgroundWorker1.CancelAsync();
this.button1.Enabled = false;
this.Close();
}
实现的效果:

{
this.progressBar1.Value = e.ProgressPercentage;
this.textBox1.Text += e.UserState.ToString(); //主窗体传过来的值,通过e.UserState.ToString()来接受
}

private delegate bool IncreaseHandle(int nValue,string vinfo);//代理创建
private IncreaseHandle myIncrease = null;//声明代理,用于后面的实例化代理
private int vMax = 100;//用于实例化进度条,可以根据自己的需要,自己改变
{
Thread thdSub = new Thread(new ThreadStart(ThreadFun));
thdSub.Start();
}
{
MethodInvoker mi = new MethodInvoker(ShowProcessBar);
this.BeginInvoke(mi);
object objReturn = null;
for (int i = 0; i < vMax; i++)
{
objReturn = this.Invoke(this.myIncrease, new object[] { 2, i.ToString() + "\r\n" });
Thread.Sleep(50);
}
}
{
myProcessBar = new Form6(vMax);
myIncrease = new IncreaseHandle(myProcessBar.Increase);
myProcessBar.ShowDialog();
myProcessBar = null;
}

控件名称:
{
InitializeComponent();
}
{
if (nValue > 0)
{
if (progressBar1.Value + nValue < progressBar1.Maximum)
{
progressBar1.Value += nValue;
this.textBox1.AppendText(nInfo);
Application.DoEvents();
progressBar1.Update();
progressBar1.Refresh();
this.textBox1.Update();
this.textBox1.Refresh();
return true;
}
else
{
progressBar1.Value = progressBar1.Maximum;
this.textBox1.AppendText(nInfo);
//this.Close();//执行完之后,自动关闭子窗体
return false;
}
}
return false;
}

C# 使用委托实现多线程调用窗体的四种方式的更多相关文章
- C# 使用委托实现多线程调用窗体的四种方式(转)
1.方法一:使用线程 功能描述:在用c#做WinFrom开发的过程中.我们经常需要用到进度条(ProgressBar)用于显示进度信息.这时候我们可能就需要用到多线程,如果不采用多线程控制进度条,窗口 ...
- Delphi中动态创建窗体有四种方式
Delphi中动态创建窗体有四种方式,最好的方式如下: 比如在第一个窗体中调用每二个,主为第一个,第二个设为动态创建 Uses Unit2; //引用单元文件 procedure TForm1.But ...
- python3.4多线程实现同步的四种方式
临界资源即那些一次只能被一个线程访问的资源,典型例子就是打印机,它一次只能被一个程序用来执行打印功能,因为不能多个线程同时操作,而访问这部分资源的代码通常称之为临界区. 1. 锁机制 threadin ...
- JAVA实现多线程的四种方式
JAVA多线程实现方式: 1.继承Thread类(无返回值) 2.实现Runnable接口(无返回值) 3.实现Callable接口,通过FutureTask包装器来创建Threak线程(有返回值) ...
- 【Linux】多线程同步的四种方式
背景问题:在特定的应用场景下,多线程不进行同步会造成什么问题? 通过多线程模拟多窗口售票为例: #include <iostream> #include<pthread.h> ...
- 【Java EE 学习 80 下】【调用WebService服务的四种方式】【WebService中的注解】
不考虑第三方框架,如果只使用JDK提供的API,那么可以使用三种方式调用WebService服务:另外还可以使用Ajax调用WebService服务. 预备工作:开启WebService服务,使用jd ...
- C#-WinForm-打开其他窗体的三种方式-Show()、设置Owner()、ShowDialog()
打开其他窗体的三种方式 Show - 例如登入界面进入主页面,直接将主页面展示出来,两个窗体互不影响 public partial class Form1 : Form { public Form1( ...
- 调用awk的三种方式
调用awk的三种方式 调用awk有三种方式,一种为Shell命令行方式,另外两种是将awk程序写入脚本文件,然后执行该脚本文件.三种方式的命令格式归纳如下: 一.在Shell命令行输入命令调用awk, ...
- 调用init方法 两种方式 一个是浏览器方法 一个是 xml中手工配置(load-on-startup)
调用init方法 两种方式 一个是浏览器方法 一个是 xml中手工配置(load-on-startup)
随机推荐
- Java——java错误(The Struts dispatcher cannot be found)
这通常是由于使用了struts标签,而没有配置相关联的filter.struts标签只有在http请求通过标签的servlet filter过滤器之后才可用,这些过滤器用来为这些标签初始化struts ...
- tessaract ocr简介
Tesseract的历史Tesseract是一个开源的OCR引擎,惠普公司的布里斯托尔实验室在1984-1994年开发完成.起初作为惠普的平板扫描仪的文字识别引擎.Tesseract在1995年UNL ...
- 字典取KEY,占位符,延迟刷新
flash 监听事件者 与 事件发出者 比如说现在有A和B,A.addChild(B)A监听鼠标点击事件那么当点击B时,target是B,currentTarget是A也就是说,currentTarg ...
- 2017CCPC秦皇岛 L题One-Dimensional Maze&&ZOJ3992【模拟】
链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3992 题意: 走迷宫,一个一维字符串迷宫,由'L'.'R'组成,分别 ...
- while与for不能互换的地方
- B - 低阶入门膜法 - D-query (查询区间内有多少不同的数)
题目链接:https://cn.vjudge.net/contest/284294#problem/B 题目大意:查询区间内有多少个不相同的数. 具体思路:主席树的做法,主席树的基础做法是查询区间第k ...
- Android WebView常见问题及解决方案汇总【很全很实用】
http://www.cnblogs.com/olartan/p/5713013.html
- CNN可解释
1 http://bindog.github.io/blog/2018/02/10/model-explanation/ http://www.sohu.com/a/216216094_473283 ...
- android 面试题(一)
1.Android中真实宽高,getWidth和getMeasuredWidth的区别:哪个计算的是真实的宽? getWidth():得到的是View在父Layout中布局好后的宽度值,如果没有父布局 ...
- 20165230田坤烨《网络对抗》Exp1 PC平台逆向破解
实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 该程序同时包含另一个代码片段,getShe ...