如何使用 backgroundworker 进程 c# 以另一种形式更改标签?

How do i change label in another form with backgroundworker process c#?

我的项目 c# 中有 2 个表单(formA 和 formB),我想 运行 当我在 formA 中单击一个按钮时在后台工作程序中进行一些处理。

我可以从 backgroundworker 更新到 formB 中的标签吗? 这是formA

中的代码
        private void button1_Click_1(object sender, EventArgs e)
    {
        backgroundWorker1.RunWorkerAsync();
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        Stimulus stimulus = new Stimulus();
        Stopwatch watch = new Stopwatch();
        stimulus.Show();
        stimulus.Invoke((MethodInvoker)delegate { stimulus.perbaharuiStimulus("+"); });
        watch.Start();
        do
        {

        } while (watch.Elapsed.Seconds != 2);
        watch.Restart();
        stimulus.Invoke((MethodInvoker)delegate { stimulus.perbaharuiStimulus("MAJU"); });
        do
        {

        } while (watch.Elapsed.Seconds != 6);
        watch.Restart();
        stimulus.Invoke((MethodInvoker)delegate { stimulus.perbaharuiStimulus(""); });
        do
        {

        } while (watch.Elapsed.Seconds != 2);
        watch.Stop();
        stimulus.Close();
    }

这里是 formB 中的代码

        public Stimulus()
    {
        InitializeComponent();
        FormBorderStyle = FormBorderStyle.None;
        WindowState = FormWindowState.Maximized;
    }
    public void perbaharuiStimulus(string stimulus)
    {
        this.Invoke((MethodInvoker)delegate
        {
            lbStimulus.Text = stimulus;
        });
    }

谢谢关注..

您可以使用 Invoke(...) 从后台工作人员以任何形式更新标签,就像您所做的那样。 (假设刺激是一个领域)。 调用一次 Invoke 就足够了。 Stimulus.Invoke 在刺激形式的控制线程上执行委托。因此,您可以决定何时分派线程。我建议在 perbarauiStimulus 中执行此操作,因为这会减少有人忘记发送呼叫的可能性。

但是您的代码存在一个潜在问题:

不要对经过的时间使用精确比较。更喜欢使用“>=”。由于您处理的是秒,这很少会成为实际问题,但它可能会导致无限循环。

如果 stimulus 不是一个字段,您必须在后台工作程序的 Stimulus 外部 创建一个实例,因为如果您在内部创建它worker 方法,表单将 运行 它的消息在后台工作线程上循环。这消除了后台工作者的使用,因为操作 运行s 现在从 sytimulus 视图同步。

您不应该在后台线程中创建表单。这样做会将表单分配给 that 线程而不是 UI 线程,这意味着表单现在与消息泵位于不同的线程上。

解决此问题的方法是在 UI 线程上调用表单的实例化和查看,然后您的后续 Invoke 调用应该可以工作。

Stimulus stimulus;

this.Invoke((MethodInvoker)delegate
{
    stimulus = new Stimulus();
    stimulus.Show();
});

//No need to invoke this since perbaharuiStimulus() calls Invoke() as well.
stimulus.perbaharuiStimulus("+");

//The rest of your code...

除此之外,您做的一切都正确。

您可以像下面这样更改您的代码,它会正常工作。

  1. 将 perbaharuiStimulus 代码更改为

    lbStimulus.Text = stimulus;
    
  2. WorkerReportsProgress改为True

  3. backgroundWorker1_DoWork改为以下

        Stimulus stimulus = new Stimulus();
        Stopwatch watch = new Stopwatch();
        backgroundWorker1.ReportProgress(1, stimulus);
        watch.Start();
        do
        {
    
        } while (watch.Elapsed.Seconds != 2);
    
        watch.Restart();
        backgroundWorker1.ReportProgress(2, stimulus);
        do
        {
    
        } while (watch.Elapsed.Seconds != 6);
    
        watch.Restart();
        backgroundWorker1.ReportProgress(3, stimulus);
        do
        {
    
        } while (watch.Elapsed.Seconds != 2);
        watch.Stop();
    
        stimulus.Invoke((MethodInvoker)delegate { stimulus.Close(); });
    
  4. 添加 backgroundWorker1_ProgressChanged 事件并在其中放入以下代码

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        Stimulus stimulus = ( Stimulus)e.UserState;
        if(e.ProgressPercentage==1)
            stimulus.perbaharuiStimulus("+");
        if (e.ProgressPercentage == 2)
            stimulus.perbaharuiStimulus("MAJU");
        if (e.ProgressPercentage == 3)
            stimulus.perbaharuiStimulus("");
    
        stimulus.Show();
    }
    

希望对您有所帮助!