winform多线程组件BackgroundWorker使用

 更新时间:2022年05月11日 11:24:14   作者:springsnow  
这篇文章介绍了winform多线程组件BackgroundWorker的使用方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

BackgroundWorker是·net里用来执行多线程任务的控件,它允许编程者在一个单独的线程上执行一些操作。

可以通过编程方式创建 BackgroundWorker,也可以将它从“工具箱”的“组件”选项卡中拖到窗体上。 如果在 Windows 窗体设计器中创建 BackgroundWorker,则它会出现在组件栏中,而且它的属性会显示在“属性”窗口中。

常用方法

  • RunWorkerAsync 开始执行后台操作。引发 DoWork 事件。
       public void RunWorkerAsync(); //启动线程,触发DoWork事件
       public void RunWorkerAsync(object argument);
  • CancelAsync 请求取消挂起的后台操作。
    注意:这个方法是将 CancellationPending 属性设置为 true,并不会终止后台操作。在后台操作中要检查CancellationPending 属性,来决定是否要继续执行耗时的操作。
  • ReportProgress引发 ProgressChanged 事件。
       public void ReportProgress(int percentProgress); //报告进度,触发ProgressChanged事件
       public void ReportProgress(int percentProgress, object userState);

常用属性

  • IsBusy:  //只读属性,用来判断当前线程是否正在工作中。
  • CancellationPending: 指示应用程序是否已请求取消后台操作。只读属性,默认为 false,当执行了 CancelAsync 方法后,值为 true。
  • WorkerSupportsCancellation:指示是否支持异步取消。要执行 CancelAsync 方法,需要先设置该属性为 true。
  • WorkerReportsProgress:指示是否能报告进度。要执行 ReportProgress 方法,需要先设置该属性为 true。

常用事件

  • DoWork: 调用 RunWorkerAsync 方法时发生。
  • ProgressChanged:可选,调用 ReportProgress 方法时发生。
  • RunWorkerCompleted:可选,后台操作已完成、被取消或引发异常时发生。

注意:在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和RunWorkerCompleted 事件与用户界面进行通信。

如果想在 DoWork 事件处理程序中和用户界面的控件通信,可在用 ReportProgress 方法。ReportProgress(int percentProgress, object userState),可以传递一个对象。ProgressChanged 事件可以从参数ProgressChangedEventArgs 类的UserState 属性得到这个信息对象。这个事件也可以实现进度条功能,把任务的进度实时呈现给用户。

简单的程序用BackgroundWorker 比 Thread 方便,Thread中和用户界面上的控件通信比较麻烦,需要用委托来调用控件的 Invoke 或BeginInvoke 方法,没有 BackgroundWorker 方便。

使用backgroundWorker步骤

  • 新建BackgroundWorder对象;

  • 根据需求, 设置是否能取消(WorkerSupportsCancellation)、是否报告进度(WorkerReportsProgress);

  • 根据需求,设置好相关事件,DoWorker、ProgressChanged、ProgressChanged;

  • 调用RunWorkerAsyns()方法,启动线程;

  • 在需要取消的位置,判断CancellationPending的值,并做相关处理;//可选

  • 在适当的位置调用ReportProgress(int percentProgress)方法,报告进度。

BackgroundWorker实例

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            backgroundWorker1.WorkerReportsProgress = true;//报告完成进度
            backgroundWorker1.WorkerSupportsCancellation = true;//允许用户终止后台线程
                                                                //绑定事件
            backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
            backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
            backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);

        }
        //开始按钮
        private void button1_Click(object sender, EventArgs e)
        {
            if (!backgroundWorker1.IsBusy)//判断backgroundWorker1是否正在运行异步操作
            {
                backgroundWorker1.RunWorkerAsync(1000);//开始执行后台异步操作,调用DoWork事件
            }
            while (backgroundWorker1.IsBusy)//等待后台运行完毕
            {
                Application.DoEvents();
            }
            MessageBox.Show("操作完成");
        }

        //取消按钮
        private void button2_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.WorkerSupportsCancellation == true)
            {
                backgroundWorker1.CancelAsync();//取消后台操作
                backgroundWorker1.Dispose();//释放资源
            }
        }

        //DoWork事件声明要执行的耗时操作
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker backgroundWorker = sender as BackgroundWorker;
            e.Result = ListNumber(backgroundWorker, e);//运算结果保存在e.Result中(在RunWorkerCompleted事件可能会使用到)
        }

        bool ListNumber(object sender, DoWorkEventArgs e)
        {
            int num = (int)e.Argument;//接收传入的参数,即RunWorkerAsync(object argument)传入的值
            for (int i = 1; i <= num; i++)
            {
                if (backgroundWorker1.CancellationPending)//判断是否请求了取消后台操作,如果为false则退出
                {
                    e.Cancel = true;//e.Cancel 是否应该取消事件
                    return false;
                }
                Thread.Sleep(10);//执行一个耗时操作
                backgroundWorker1.ReportProgress(i * 100 / num, i);//报告完成进度

            }
            return true;
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {

            progressBar1.Value = e.ProgressPercentage;//将完成进度数据传给进度条
            label1.Text = e.ProgressPercentage + "%";
            //将中间计算结果在ListBox控件中显示出来
            listBox1.Items.Add(e.UserState);//接收ReportProgress方法传递过来的userState
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled == true) //e.Cancelled指示异步操作是否已被取消
            {
                MessageBox.Show("Canceled!");
            }
            else if (e.Error != null) //e.Error 指示异步操作期间发生的错误
            {
                MessageBox.Show("Error: " + e.Error.Message);
            }
            else
            {
                MessageBox.Show(e.Result.ToString());  //e.Result 获取异步操作结果的值,即DoWork事件中,Result设置的值。
            }

        }
    }

对Winform窗体控件进行安全调用

(WinForm中实现多线程的首选方法是backgroundWorker)

Thread thread = new Thread(SetLabel);//另开一个线程上设置Label的属性
thread.Start();
 
delegate void Action(string args);//Net3.5自带的Action无参数无返回值
private void SetLabel()
{
    Action action = delegate (string args)
    {
        this.label1.Text = args;
    };
    if (this.InvokeRequired)//判断当前代码是运行于创建该控件的线程之上,还是运行于另一个线程之上。
        this.Invoke(action, "XXX");//注意控件的Inovoke和BeginInvoke委托的方法都执行在UI线程上。对Control的Invoke方法可以使用一个简单的系统委托MethodInvoker无参数返回Void调用。
    else
        action("XXX");
}

到此这篇关于winform多线程组件BackgroundWorker的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • C# 通过 inline-asm 解决嵌入x86汇编

    C# 通过 inline-asm 解决嵌入x86汇编

    此篇文章通过C#语言解决嵌入x86汇编,主要通过INline-asm方法来实现,下面我通过图片和代码的形式给大家分享下,需要的朋友可以参考下
    2015-07-07
  • c#和javascript函数相互调用示例分享

    c#和javascript函数相互调用示例分享

    在webBrowser使用过程中为了C#和JS通讯,webBrowser必须设置ObjectForScripting的属性,它是一个object,这个object可以提供给webBrowser控件载入的网页上的script访问
    2014-01-01
  • C# Oracle批量插入数据进度条的实现代码

    C# Oracle批量插入数据进度条的实现代码

    这篇文章主要介绍了C# Oracle批量插入数据进度条的实现代码,需要的朋友可以参考下
    2018-04-04
  • C#中DataTable和List互转的示例代码

    C#中DataTable和List互转的示例代码

    很多场景下,我们需要将List转换成为DataTable,本文主要介绍了C#中DataTable和List互转,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • C#定时器和随机数

    C#定时器和随机数

    在前一篇中我们介绍了键盘和鼠标事件,其实还有一个非常常用的事件,就是定时器事件,如果要对程序实现时间上的控制,那么就要使用到定时器。而随机数也是很常用的一个功能,在我们要想产生一个随机的结果时就要使用到随机数。本文我们就来简单介绍一下定时器和随机数。
    2015-06-06
  • C# FileStream实现多线程断点续传

    C# FileStream实现多线程断点续传

    这篇文章主要为大家详细介绍了C# FileStream实现多线程断点续传,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • c# 连接access数据库config配置

    c# 连接access数据库config配置

    c# 连接access数据库config配置,需要的朋友可以参考一下
    2013-02-02
  • C#队列Queue多线程用法实例

    C#队列Queue多线程用法实例

    这篇文章主要介绍了C#队列Queue多线程用法,实例分析了队列的相关使用技巧,需要的朋友可以参考下
    2015-05-05
  • C#实现扫描局域网内的所有IP和端口

    C#实现扫描局域网内的所有IP和端口

    这篇文章主要为大家详细介绍了如何利用C#实现扫描局域网内的所有IP和端口的功能,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-12-12
  • c#正反序列化XML文件示例(xml序列化)

    c#正反序列化XML文件示例(xml序列化)

    这篇文章主要介绍了c#正反序列化XML文件示例,可以将对象序列化为XML文本或者文件,或者将XML文件或文本反序列化为对象,要求进行序列化的对象不能出现序列化异常,支持类的嵌套,要求类的属性为public
    2014-03-03

最新评论