我想从表单中启动后台工作程序。
private void button2_Click(object sender, EventArgs e)
{
backgroundWorker2.RunWorkerAsync();
}
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
ExtClass.doit("Hello", "World");
}
后台工作人员在文本框中插入“Hello World”。
public static void doit(string a, string b)
{
Form F1 = Application.openForms[0] as Form1;
F1.textbox1.Text = a + b;
}
但是我得到了一个例外。 如何从后台工作者访问表单控件?
答案 0 :(得分:2)
后台工作人员在背景中完成工作(顾名思义)。
所有Control
个对象都设计为不是线程安全的。您只能从创建它们的线程(通常称为UI线程)访问它们。
虽然有很多方法可以在UI线程中执行代码块,但您应该首先从根本上看一下您的设计。使用后台工作者的想法是在后台工作; 不涉及与用户界面交互的工作。
如果您需要从UI获取信息来完成工作,您应该在启动后台工作程序之前获取它并将信息作为参数传递给工作方法。如果要使用操作结果更新UI,则应使用已完成的事件处理程序。 (它总是在UI线程中运行; BGW类会为您处理。)如果您需要更新进度条或带有进度的标签,则应使用进度更新事件并在BGW上调用更新进度。进度更新事件也在UI线程中运行。
答案 1 :(得分:1)
F1.Invoke(new MethodInvoker(()=> { F1.textbox1.Text = a + b; }));
答案 2 :(得分:0)
您需要有一个返回表单的引用,并使用Invoke或Begin / End Invoke传递修改表单的方法。
要保留引用,我建议您使用RunWorkerAsync(Object)传递控件并通过DoWork Arg Argument获取引用。
答案 3 :(得分:0)
为了解决问题,您应该创建Form1
引用而不是Form
的引用,因为Form
没有textBox1
字段,而是Form1
1}}确实这是异常的来源,你应该改变这个:
Form F1 = Application.OpenForms[0] as Form1;
进入这个
Form1 F1 = Application.OpenForms[0] as Form1;
然后你应该调用对textBox1字段的访问(如果需要),因为你是从另一个线程访问它(DoWork在另一个线程中执行,但RunWorkerCompleted在UI线程中)。因此,完整的代码应该是这样的:
public static void doit(string a, string b)
{
Form1 F1 = Application.openForms[0] as Form1;
if(F1.InvokeRequired)
F1.Invoke(new MethodInvoker(delegate() { F1.Text = a + b; });
else
F1.Text = a + b;
}
答案 4 :(得分:0)
我需要一些帮助。
我在另一个c#项目中运行后台工作程序。 问题是这个项目有一个巨大的组合框和文本框,后台工作者在运行时访问。
所以我怎样才能在GUI中访问控件而不将它们全部放到a,
textbox1.Invoke(new MethodInvoke(()............}));选项......