如何使用后台工作进程 c# 更改另一种形式的标签?



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

我可以在表单 B 中从后台工作者更新为标签吗? 这是形式A中的代码

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();
}

和下面的代码在形式B中

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

感谢您的关注..

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

  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();
    }
    

希望对您有所帮助!

您不应该在后台线程中创建表单。这样做会将表单分配给线程而不是 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...

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

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

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

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

如果stimulus不是字段,则必须在后台工作线程外部创建Stimulus实例,因为如果在 worker Method(工作器方法(中创建它,窗体将在后台工作线程上运行其消息循环。这消除了后台工作线程的使用,因为操作现在从 sytimulus 视图同步运行。

最新更新