我的项目c#中有2个表单(formA和formB),当我单击formA中的按钮时,我想在backgroundworker中运行某些进程。
我可以从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;
});
}
谢谢您的关注。
答案 0 :(得分:2)
您可以像下面那样更改代码,这样就可以正常工作。
将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();
}
希望对您有帮助!
答案 1 :(得分:0)
您可以使用Invoke(...)
从后台工作人员以任何形式更新标签,就像这样做一样。 (假设刺激是一个领域)。
调用一次Invoke就足够了。 Stimulus.Invoke
在刺激形式的控制线程上执行委托。因此,您可以在调度线程时决定。我建议在perbarauiStimulus
中进行此操作,因为这样可以减少有人忘记分派呼叫的机会。
但是您的代码存在一个潜在问题:
不要对经过的时间使用精确的比较。优先使用'> ='。由于您要处理的秒数很少会成为实际问题,但可能会导致无限循环。
如果stimulus
不是字段,则必须在后台工作程序的Stimulus
外部实例中创建一个实例,因为如果您在worker方法中创建该实例,窗体将在后台工作线程上运行其消息循环。这样就无需使用后台工作程序,因为该操作现在可以从同步视图中同步运行。
答案 2 :(得分:0)
您不应该在后台线程中创建表单。这样做会将表单分配给那个线程而不是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...
除此之外,您可以正确地进行所有操作。