繁体   English   中英

线程和BackgroundWorker

[英]Thread and BackgroundWorker

我有一个 WinForm C# 应用程序,我想执行一些可能需要几秒钟才能完成的计算。 所以为了避免线程问题和应用程序冻结,我使用了BackgroundWorker 当我第一次单击按钮时,一切都很好,开始按钮变得不可见,取消按钮变为可见,应用程序没有冻结问题,进度条更改成功。 但是第二次,当我点击按钮时,几秒钟开始按钮变得不可见,取消按钮也看不见,但它必须是可见的,并且应用程序进入冻结状态,然后一切都会变好。 我不知道为什么它会起作用,因为我只需要在第一次尝试时使用。 这里是我使用的代码。

注意:我已将 BackgroundWorker 表单工具箱添加到我的表单中。

private void btnStart_Click(object sender, EventArgs e)
{
     btnStart.Visible = false;
     btnCancel.Visible = true;
     progressBar1.Value = 0;
     progressBar1.Visible = true;
     backGroundWorker.RunWorkerAsync();

}

private void backGroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
   Calculate(backGroundWorker, e);
}

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

private void backGroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
   btnStart.Visible = true;
   btnCancel.Visible = false;
   progressBar1.Visible = false;
}

void Calculate(BackgroundWorker instance, DoWorkEventArgs e)
{
 
  // Do Some Works
  instance.ReportProgress(counter);

}

你快完成了。 您只是忘记让您的后台工作人员支持取消。 此外:您的后台工作人员不应使用后台工作人员以外的任何内容。 如果后台工作人员需要表单中的一些数据来执行任务,请在开始工作时将其作为参数传递。

使用设计器可以完成以下许多工作。 如果你愿意,你可以自己编程。 处理表单时不要忘记处理后台工作人员

BackgroundWorker backgroundWorkder = new BackgroundWorker
{
    WorkerReportsProgres = true,
    WorkerSupportsCancellation = true,
}

// ensure that backgroundWorker is disposed when the form is disposed:
this.Components.Add(backgroundWorker); 
// alternative: react on event from closed

backgroundWorker.DoWork += OnDoBackGroundWork;
backgroundWorker.ProgressChanged += OnProgressReported;
backgroundWorker.RunWorkerCompleted += OnBackgroundWorkCompleted;

第一个事件处理程序将由 backgroundWorker 执行。 此事件处理程序不应触及表单中的任何内容。

后面的两个事件处理程序将由主线程执行。 他们可以使用表单中的项目。

private void StartBackgroundWork()
{
    // TODO: enable / disable buttons; show progress bar

    // if your backgroundWorker needs parameters:
    MyBackgroundParameters params = new MyBackgroundParameters()
    {
        Text = this.textBox1.Text,
        Value = this.comboBox1.SelectedIndex,
        ...
    };
    this.backgroundWorker.RunWorkerAsync(params);
}

private void CancelBackgroundwork()
{
    this.backgroundWorker.CancelAsync();
}

无需检查 backgroundWorker 是否已经完成。 如果是这样,cancelAsync 不会做任何事情。 此外,如果您要检查IsBusy ,那么在您 CancelAsync 之前, backgroundWorker 可能会完成。

事件处理程序:

private void OnDoBackgroundWork(object sender, DoWorkEventArgs e)
{
    // if there are several backgroundWorkers that could call this, you should check 
    // the sender, to determine what work should be done and which parameters are passed
    BackgroundWorkder backgroundWorker = (BackgroundWorker)sender;
    MyBackGroundParameters params = (MyBackGroundParameters) e.DoWorkEventArgs;

    // use these params to do your calculations.
    // regularly, check if cancellationpending
    bool calculationFinished = false;
    while (!calculationFinished && !backgroundWorker.CancellationPending)
    {
        // do a short part of the calculation
        progress = performNextCalculationStep();
        backgroundWorker.ReportProgress(...)
        calculationFinished = ...
    }

    // if here, either calculation finished, or cancelled:
    MyBackgroundResult backgroundResult;
    if (calculationFinished)
    {
        backgroundResult = new MyBackgroundResult
        {
            ... // fill with values if completed
        };
    }
    else
    {
        // cancelled
        backgroundResult = new MyBackgroundResult
        {
            ... // fill with values if cancelled
        };
    }
    e.Result = backgroundResult;
}

在这里,我有参数来指示结果中的计算是完成还是取消。 如果需要,您还可以返回不同的对象。 事件处理程序应该检查对象的类型以查看计算是否被取消。

private void backGroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    btnStart.Visible = true;
   btnCancel.Visible = false;
   progressBar1.Visible = false;

   MyBackgroundResult result = (MyBackgroundResult)e.Result;
   this.ProcessResult(result);
}

不要忘记订阅表单关闭事件,并检查后台工作人员是否仍然很忙。 询问接线员是否可以取消这项工作。 如果不是,则取消关闭,如果可以取消,则取消后台工作并在关闭的事件窗体中等待完成。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM