1、方法一:使用线程

功能描述:在用c#做WinFrom开发的过程中。我们经常需要用到进度条(ProgressBar)用于显示进度信息。这时候我们可能就需要用到多线程,如果不采用多线程控制进度条,窗口很容易假死(无法适时看到进度信息)。下面我就简单结合一个我写的例子给大家做一个介绍。

第一步:设计界面,注意需要引用 using System.Threading;

控件名称分别为:
progressBar1;label1;textBox1;button1;
第二步:定义一个代理,用于更新ProgressBar的值(Value)及在执行方法的时候,返回方法的处理信息。

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");
            }
        }

程序运行效果图:

 
=========================================================================================
2、第二种方法:
     功能描述:该种方法通过控件backgroundWorker1实现,进度条。却进度条在一个模板窗体内。
 
第一步:主窗体设计:
 

控件名称:

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控件选好事件。

第三步:设置子窗体(及显示进度条的窗体):

控件名称:
progressBar1;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;
        }

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();
        }

实现的效果:

注意:如果在程序为执行完,就点击取消的话,很有可能会报错的,这时候,你就修改一个方法:backgroundWorker1_ProgressChanged
如下:
        void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
            this.textBox1.Text += e.UserState.ToString(); //主窗体传过来的值,通过e.UserState.ToString()来接受
        }
       把这个方法,替换上边的那个方法,就可以了。
=====================================================================================================
4、第四种方法:
     功能描述:本方法实现进度条显示,方法执行信息反馈显示。用到的技术点为 线程与代理。
     
    步骤一:添加主页面。

控件名称:
button1;
 
  步骤二:主页面后台代码
        using System.Threading;//引用此命名
 
        //创建代理。
        private Form6 myProcessBar = null;//弹出的子窗体(用于显示进度条)
        private delegate bool IncreaseHandle(int nValue,string vinfo);//代理创建
        private IncreaseHandle myIncrease = null;//声明代理,用于后面的实例化代理
        private int vMax = 100;//用于实例化进度条,可以根据自己的需要,自己改变
 
        private void button1_Click(object sender, EventArgs e)
        {
            Thread thdSub = new Thread(new ThreadStart(ThreadFun));
            thdSub.Start();
        }
        private void ThreadFun()
        {
            MethodInvoker mi = new MethodInvoker(ShowProcessBar);
            this.BeginInvoke(mi);
            Thread.Sleep(100);
            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);
            }
        }
        private void ShowProcessBar()
        {
            myProcessBar = new Form6(vMax);
            myIncrease = new IncreaseHandle(myProcessBar.Increase);
            myProcessBar.ShowDialog();
            myProcessBar = null;
        }
 
步骤三:创建子窗体

控件名称:

progressBar1;textBox1
 
步骤四:子窗体,后台代码
        public Form6(int vMax)
        {
            InitializeComponent();
            this.progressBar1.Maximum = vMax;
        }
        public bool Increase(int nValue,string nInfo)
        {
            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# 使用委托实现多线程调用窗体的四种方式的更多相关文章

  1. C# 使用委托实现多线程调用窗体的四种方式(转)

    1.方法一:使用线程 功能描述:在用c#做WinFrom开发的过程中.我们经常需要用到进度条(ProgressBar)用于显示进度信息.这时候我们可能就需要用到多线程,如果不采用多线程控制进度条,窗口 ...

  2. Delphi中动态创建窗体有四种方式

    Delphi中动态创建窗体有四种方式,最好的方式如下: 比如在第一个窗体中调用每二个,主为第一个,第二个设为动态创建 Uses Unit2; //引用单元文件 procedure TForm1.But ...

  3. python3.4多线程实现同步的四种方式

    临界资源即那些一次只能被一个线程访问的资源,典型例子就是打印机,它一次只能被一个程序用来执行打印功能,因为不能多个线程同时操作,而访问这部分资源的代码通常称之为临界区. 1. 锁机制 threadin ...

  4. JAVA实现多线程的四种方式

    JAVA多线程实现方式: 1.继承Thread类(无返回值) 2.实现Runnable接口(无返回值) 3.实现Callable接口,通过FutureTask包装器来创建Threak线程(有返回值) ...

  5. 【Linux】多线程同步的四种方式

    背景问题:在特定的应用场景下,多线程不进行同步会造成什么问题? 通过多线程模拟多窗口售票为例: #include <iostream> #include<pthread.h> ...

  6. 【Java EE 学习 80 下】【调用WebService服务的四种方式】【WebService中的注解】

    不考虑第三方框架,如果只使用JDK提供的API,那么可以使用三种方式调用WebService服务:另外还可以使用Ajax调用WebService服务. 预备工作:开启WebService服务,使用jd ...

  7. C#-WinForm-打开其他窗体的三种方式-Show()、设置Owner()、ShowDialog()

    打开其他窗体的三种方式 Show - 例如登入界面进入主页面,直接将主页面展示出来,两个窗体互不影响 public partial class Form1 : Form { public Form1( ...

  8. 调用awk的三种方式

    调用awk的三种方式 调用awk有三种方式,一种为Shell命令行方式,另外两种是将awk程序写入脚本文件,然后执行该脚本文件.三种方式的命令格式归纳如下: 一.在Shell命令行输入命令调用awk, ...

  9. 调用init方法 两种方式 一个是浏览器方法 一个是 xml中手工配置(load-on-startup)

    调用init方法 两种方式 一个是浏览器方法 一个是 xml中手工配置(load-on-startup)

随机推荐

  1. mysql的事件

    mysql的事件定时器的使用: SHOW VARIABLES LIKE 'event_scheduler' --查询event_scheduler开启状态 SET GLOBAL event_sched ...

  2. python学习笔记9--日志模块logging

    我们在写程序的时候经常会打一些日志来帮助我们查找问题,这次学习一下logging模块,在python里面如何操作日志.介绍一下logging模块,logging模块就是python里面用来操作日志的模 ...

  3. 五、u-boot 启动流程---u-boot.lds

    5.1 u-boot.lds  链接脚本分析 uboot 编译出来的第一个链接脚本就是执行 u-boot.lds 链接脚本,去掉里面无用的和没有定义的,进行分析. /* 配置头文件,自动生成的,包含芯 ...

  4. pyinstaller 打包不成功,提示inporterror 缺少xlrd、xlwt

    问题:pyinstaller 打包不成功,提示inporterror 缺少xlrd.xlwt 解决:将 pypiwin 230 改为 219

  5. WEB即时通信

    问题 传统的浏览器通信方式:基于HTTP协议的请求/响应模式. 早期:通过刷新浏览器来更新服务器端的数据 后来Ajax(XMLHttpRequest是核心):可以不用刷新浏览器更新服务器端数据.但是这 ...

  6. js中,for循环里面放ajax,ajax访问不到变量以及每次循环获取不到数据问题总结

    想在点击"终端控制"的时候能够开启多个窗口对多个终端进行管理: /**提交事件**/ $("#terminalControl").bind("clic ...

  7. FPN 学习笔记

    通常,利用网络对物体进行检测时,浅层网络分辨率高,学到的是图片的细节特征,深层网络,分辨率低,学到的更多的是语义特征. 1).通常的CNN使用如下图中显示的网络,使用最后一层特征图进行预测 例如VGG ...

  8. 带事件的Bootstrap模态框的使用2

    模态框中显示一些基本的数据以及触发一些基本的JS函数 <%@ page language="java" contentType="text/html; charse ...

  9. .NET中制做对象的副本(三)通过序列化和反序列化为复杂对象制作副本

    1.类的定义 /// <summary> /// 学生信息 /// </summary> [Serializable] public class Stu { /// <s ...

  10. ARMV8 datasheet学习笔记4:AArch64系统级体系结构之编程模型(1)-EL/ET/ST

    1.前言 ARMV8系统级编程模型主要包括异常级别.运行状态.安全状态.同步异常.异步异常.DEBUG 本文主要对系统级编程模型做一个概要介绍 2. 异常级别 2.1 Exception level概 ...