我在我的项目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();
}
这是B表格中的代码
public Stimulus()
{
InitializeComponent();
FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
}
public void perbaharuiStimulus(string stimulus)
{
this.Invoke((MethodInvoker)delegate
{
lbStimulus.Text = stimulus;
});
}
感谢您的关注..
您可以像下面一样更改代码,它会正常工作。
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(...)
一样从后台工作者更新任何形式的标签。 (假设刺激是一个领域)。只需调用一次Invoke就足够了。 Stimulus.Invoke
在刺激形式的控制线程上执行委托。所以你可以决定,你派遣线程。我建议在perbarauiStimulus
中这样做,因为那会减少有人忘记拨打电话的机会。
但是您的代码存在一个潜在问题:
不要对经过的时间使用精确比较。首选使用'> ='。由于你正在处理秒,这很少是一个实际问题,但它可能会导致无限循环。
如果stimulus
不是一个字段,你必须在后台worker之外创建一个Stimulus
实例,因为如果你在worker方法中创建它,表单将在后台工作线程上运行它的消息循环。这消除了后台工作程序的使用,因为操作现在从sytimulus视图同步运行。