如何使用BackgroundWorker?


68

我知道它有3种方法。在我的程序中,我有一种发送消息的方法。这通常很晚,并且程序有时根本不发送响应按钮按下的消息。有时可能比我期望的要晚5秒钟,程序会冻结。我想使用aBackgroundWorker按预期方式发送消息,并允许程序始终正常运行。我有用于在按钮处理程序中发送消息的代码。现在,我将这些等效代码放在哪里?我希望所有这些仍然可以通过按按钮来处理。

这是合适的处理程序吗?

backgroundWorker1.RunWorkerAsync();

并在:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {}

我要把我的代码放在按钮处理程序中吗?而这之前:

carga.progressBar1.Minimum = 0;
carga.progressBar1.Maximum = 100;

Carga是ProgressBar所在的另一种形式。在这种情况下如何使用BackgroundWorker?

Answers:


93

您只能从ProgressChangedRunWorkerCompleted事件处理程序更新进度条,因为它们与UI线程同步。

基本思想是。Thread.Sleep只是在这里模拟一些工作。将其替换为您的真实路由呼叫。

public Form1()
{
    InitializeComponent();

    backgroundWorker1.DoWork += backgroundWorker1_DoWork;
    backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
    backgroundWorker1.WorkerReportsProgress = true;
}

private void button1_Click(object sender, EventArgs e)
{
    backgroundWorker1.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    for (int i = 0; i < 100; i++)
    {
        Thread.Sleep(1000);
        backgroundWorker1.ReportProgress(i);
    }
}

private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage;
}

在您的button1_Click()示例中-如何将后台工作人员返回的数据返回到主(UI)线程?
Nicholas Kreidberg '17

奇怪的是,我在从ProgressChanged方法更新UI(WPF进度栏)时遇到了一个例外。另外,stackoverflow.com/questions/9732709/…似乎也有类似的问题,并指出了对的需求Application.Current.Dispatcher.Invoke()。有什么想法吗?
比尔·霍格

为什么几乎在每种方法中都采用对象发送者参数。@Aza
Lahiru Gamage,

1
@LahiruGamage它是DoWork,ProgressChanged等所必需的,可用于找出哪个对象称为方法。检查文件,以了解更多:docs.microsoft.com/en-us/dotnet/api/...
基督教塞勒

1
@CodyBugstein谢谢,科迪!如果您往下看,Microsoft Docs将指定:“无法明确重载化合物赋值运算符。但是,当您重载二进制运算符时,相应的化合物赋值运算符(如果有)也会隐式重载。例如,+ =被求值使用+,可以重载。”
Su Llewellyn

70

我知道这有点老了,但是如果其他初学者正在研究中,我将分享一些涵盖更多基本操作的代码,这是另一个示例,还包括取消该过程并报告的选项向用户显示过程状态。在上述解决方案中,我将添加Alex Aza提供的代码

public Form1()
{
    InitializeComponent();

    backgroundWorker1.DoWork += backgroundWorker1_DoWork;
    backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
    backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;  //Tell the user how the process went
    backgroundWorker1.WorkerReportsProgress = true;
    backgroundWorker1.WorkerSupportsCancellation = true; //Allow for the process to be cancelled
}

//Start Process
private void button1_Click(object sender, EventArgs e)
{
    backgroundWorker1.RunWorkerAsync();
}

//Cancel Process
private void button2_Click(object sender, EventArgs e)
{
    //Check if background worker is doing anything and send a cancellation if it is
    if (backgroundWorker1.IsBusy)
    {
        backgroundWorker1.CancelAsync();
    }

}

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    for (int i = 0; i < 100; i++)
    {
        Thread.Sleep(1000);
        backgroundWorker1.ReportProgress(i);

        //Check if there is a request to cancel the process
        if (backgroundWorker1.CancellationPending)
        {
            e.Cancel = true;
            backgroundWorker1.ReportProgress(0);
            return;
        }
    }
    //If the process exits the loop, ensure that progress is set to 100%
    //Remember in the loop we set i < 100 so in theory the process will complete at 99%
    backgroundWorker1.ReportProgress(100);
}

private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage;
}

private void backgroundWorker1_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
    if (e.Cancelled)
    {
         lblStatus.Text = "Process was cancelled";
    }
    else if (e.Error != null)
    {
         lblStatus.Text = "There was an error running the process. The thread aborted";
    }
    else
    {
       lblStatus.Text = "Process was completed";
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.