Backgroundworker与Thread的区别

最近项目要用到,窗体Form程序要在后台开启几个子线程,负责和其他端进行通信,异步读写,并且来更改UI。在网上查了有Backgroundworker与Thread两种方法。

1.Backgroundworker

BackgroundWorker是微软的在.net Framwork中添加的一个组件,主要对线程的访问提供了一种安全的方式。简单的说就是对Thread的一次封装。

首先介绍一下BackgroundWorker的相关属性和方法:

  属性:

  WorkerReportsProgress:是否可以报告进度。

  WorkerSupportsCancellation:是否允许异步中止。

  IsBusy:是否在运行。

  CancellationPending:判断BackgroundWorker是否已经异步取消。

  方法:

  RunWorkerAsync:开始执行任务。触发DoWork事件

  ReportProgress:异步提醒,触发ProgressChanged事件,但是这个如果可以使用,必须设置WorkerReportsProgress为True

  CancelAsync:取消BackgroundWorker操作。

  事件:

  DoWork:执行RunWorkerAsync后触发,异步执行的认为。

  ProgressChanged:执行ReportProgress时触发,异步获得进度。

  RunWorkerCompleted:线程结束时触发,主要有成功结束,发生异常或者取消时发生。

一个简单的例子:

public partial class MainWindow : Window
{

    private BackgroundWorker m_BackgroundWorker;// 申明后台对象

    public MainWindow()
    {
        InitializeComponent();

        m_BackgroundWorker = new BackgroundWorker(); // 实例化后台对象

        m_BackgroundWorker.WorkerReportsProgress = true; // 设置可以通告进度
        m_BackgroundWorker.WorkerSupportsCancellation = true; // 设置可以取消

        m_BackgroundWorker.DoWork += new DoWorkEventHandler(DoWork);
        m_BackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(UpdateProgress);
        m_BackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CompletedWork);

        m_BackgroundWorker.RunWorkerAsync(this);
    }


    void DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker bw = sender as BackgroundWorker;
        MainWindow win = e.Argument as MainWindow;

        int i = 0;
        while ( i <= 100 )
        {
            if (bw.CancellationPending)
            {
                e.Cancel = true;
                break;
            }

            bw.ReportProgress(i++);

            Thread.Sleep(1000);

        }
    }

    void UpdateProgress(object sender, ProgressChangedEventArgs e)
    {
        int progress = e.ProgressPercentage;

        label1.Content = string.Format("{0}",progress);
    }


    void CompletedWork(object sender, RunWorkerCompletedEventArgs e)
    {
        if ( e.Error != null)
        {
            MessageBox.Show("Error");
        }
        else if (e.Cancelled)
        {
            MessageBox.Show("Canceled");
        }
        else
        {
            MessageBox.Show("Completed");
        }
    }


    private void button1_Click(object sender, RoutedEventArgs e)
    {
        m_BackgroundWorker.CancelAsync();
    }
}

 以上代码摘录至:https://www.cnblogs.com/tom-tong/archive/2012/02/22/2363965.html

2.Thread

BackgroundWorker就是一个高级控件,方便使用Thread,后者是前者的灵魂或基础
直接使用后者难度稍大,但换来的是灵活方便。

Thread的使用就比较麻烦了,对于尤其是对异步提醒来说,需要写委托,代码量是很多,但是对于BackgroundWorker来说,却没有线程暂停和继续的方法。但是对于一般的来说,这些功能也是不用的,而且在微软的文档中还提到了,Thread的Resume和Suspend已经不推荐使用。

一个简单的例子:

using System;
using System.Threading;

namespace ThreadsComm
{
public delegate void ReadParamEventHandler(string sParam);
class MyThread
{
public Thread thread1;
private static ReadParamEventHandler OnReadParamEvent;
public MyThread()
{
thread1 = new Thread(new ThreadStart(MyRead));
thread1.IsBackground = true;
thread1.Start();
}
public event ReadParamEventHandler ReadParam
{
add { OnReadParamEvent += new ReadParamEventHandler(value);}
remove{ OnReadParamEvent -= new ReadParamEventHandler(value);}
}
protected void MyRead()
{
int i = 0;
while (true)
{
Thread.Sleep(1000);
i = i + 1;
OnReadParamEvent(i.ToString());//触发事件
}
}
}
}
using System;
using System.Windows.Forms;

namespace ThreadsComm
{
public partial class Form1 : Form
{
private static string param = “”;
public Form1()
{
InitializeComponent();
MyThread thread1 = new MyThread();
thread1.ReadParam += this.OnRead;
}

    private void OnRead(string sParam)
    {
        param = sParam;
        Object[] list = { this,System.EventArgs.Empty};
        this.lblShow.BeginInvoke(new EventHandler(LabelShow), list);
    }
    protected void LabelShow(Object o, EventArgs e)
    {
        this.lblShow.Text = param;
    }
}

}
以上代码摘录至:https://blog.csdn.net/richerg85/article/details/7659180#,具体讲解说的很明白了。

3.总结

当你执行的任务较简单,不需要复杂控制时使用BackgroundWorker,较为方便;当你要执行的任务需要复杂控制(如线程同步)时,要自己 创建线程。毕竟,如果我们要实用多个线程,还需要往窗体中加好几个BackgroundWorker控件。

如果有其他使用意见和建议,欢迎大家提出来。

原文出处:qq_16739693

原文链接:https://blog.csdn.net/qq_16739693/article/details/88740301

本文观点不代表Dotnet9立场,转载请联系原作者。

发表评论

登录后才能评论