我的项目 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;
});
}
感谢您的关注..
您可以像下面这样更改代码,它会正常工作。
-
将perbaharuiStimulus代码更改为
lbStimulus.Text = stimulus;
-
将
WorkerReportsProgress
更改为True
-
将
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(); });
-
添加
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 视图同步运行。