如何使用BackgroundWorker?

82

我知道它有3种方法。在我的程序中,我有一个发送消息的方法。这个程序经常迟到,有时按下按钮后根本没有发送消息。有时比我预期的晚5秒,程序会冻结。我想使用BackgroundWorker来按预期发送消息,并允许程序始终正常运行。我之前的代码是在按钮处理程序中发送消息。现在我应该把这个相同的代码放在哪里?我希望所有这些仍然由一个按钮触发处理。

这是否是适当的处理程序?

backgroundWorker1.RunWorkerAsync();

并且在:

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

我将把我的代码放在按钮处理程序中? 并且这是之前的:

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

Carga是我的另一个窗体,在这个场景中我该如何使用BackgroundWorker?

3个回答

110

只能从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)线程? - niczak
奇怪,我的ProgressChanged方法中更新UI(WPF进度条)时出现了异常。此外,https://dev59.com/8Gkw5IYBdhLWcg3wqMU0#43455920似乎有类似的问题,并引用了需要使用`Application.Current.Dispatcher.Invoke()`的解决方法。你对此有什么想法吗? - Bill Hoag
为什么我们在几乎每个方法中都要使用 object sender 参数呢?@Aza - Lahiru Gamage
1
@LahiruGamage 它是 DoWork、ProgressChanged 等所需的,可以用来查找调用该方法的对象。请查看文档以了解更多信息:https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.backgroundworker.dowork?view=netframework-4.7.1 - Christian Seiler
1
@CodyBugstein 谢谢,Cody!如果你往下看,Microsoft文档指定:“复合赋值运算符不能显式地重载。 但是,当您重载二元运算符时,对应的复合赋值运算符(如果有)也会隐式重载。例如,+=使用+进行求值,可以重载。” - Su Llewellyn
显示剩余3条评论

81

我知道这有点旧了,但是如果还有其他初学者遇到这个问题的话,我会分享一些代码,涵盖更多基本操作,下面是另一个例子,还包括取消进程的选项,并向用户报告进程的状态。我将在上面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";
    }
}

-1

试试这个:

    private BackgroundWorker worker;

    public MainWindow()
    {
        InitializeComponent();
        InitializeBackgroundWorker();
    }

    private void InitializeBackgroundWorker()
    {
        worker = new BackgroundWorker
        {
            WorkerReportsProgress = true,
            WorkerSupportsCancellation = true
        };

        worker.DoWork += Worker_DoWork;
        worker.ProgressChanged += Worker_ProgressChanged;
        worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
    }

    private void Worker_DoWork(object sender, DoWorkEventArgs e)
    {
        // Simulate a time-consuming operation
        for (int i = 1; i <= 100; i++)
        {
            if (worker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }

            // Do the actual work here
            Thread.Sleep(100);

            // Report progress to UI thread
            worker.ReportProgress(i);
        }
    }

    private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar.Value = e.ProgressPercentage;
    }

    private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Cancelled)
        {
            MessageBox.Show("Operation was canceled.", "Canceled", MessageBoxButton.OK, MessageBoxImage.Information);
        }
        else if (e.Error != null)
        {
            MessageBox.Show("Error occurred: " + e.Error.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
        }
        else
        {
            MessageBox.Show("Operation completed successfully.", "Completed", MessageBoxButton.OK, MessageBoxImage.Information);
        }
    }

    private void StartButton_Click(object sender, RoutedEventArgs e)
    {
        if (!worker.IsBusy)
        {
            // Start the background worker
            worker.RunWorkerAsync();
        }
    }

    private void Cancel_Click(object sender, RoutedEventArgs e)
    {
    worker.CancelAsync();

    }

你的回答可以通过提供更多支持性信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的回答是否正确。你可以在帮助中心找到关于如何撰写好回答的更多信息。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接