2

我想从表单启动后台工作人员。

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

但我得到一个例外。如何从后台工作人员访问表单控件?

4

5 回答 5

2

后台工作人员在后台工作(顾名思义)。

所有Control对象都被设计为不是线程安全的。您只能从创建它们的线程(通常称为 UI 线程)访问它们。

虽然有多种方法可以在 UI 线程中执行代码块,但您应该首先从根本上了解您的设计。使用后台工作者的想法是在后台工作;涉及与用户界面交互的 工作。

如果您需要从 UI 获取信息来完成工作,您应该在启动后台工作程序之前获取它并将信息作为参数传递给工作方法。如果您想使用操作结果更新 UI,您应该使用已完成的事件处理程序。(这将始终在 UI 线程中运行;BGW 类会为您处理。)如果您需要使用进度更新进度条或标签,您应该使用进度更新事件并在 BGW 上调用更新进度。进度更新事件也在 UI 线程中运行。

于 2012-11-16T17:43:03.280 回答
1
F1.Invoke(new MethodInvoker(()=> { F1.textbox1.Text = a + b; }));
于 2012-11-16T17:41:24.890 回答
0

我需要一点帮助。

我在另一个 c# 项目中运行后台工作程序。问题是这个项目有一个巨大的组合框和文本框,后台工作人员在运行时访问。

那么我如何在 GUI 中访问控件而不将它们全部放在一个,

textbox1.Invoke(new MethodInvoke(()............})); 选项...

于 2012-11-20T12:05:50.220 回答
0

您需要返回对表单的引用,并使用 Invoke 或 Begin/End Invoke 传入修改表单的方法。

要保存引用,我建议您使用传递控件的RunWorkerAsync(Object)并通过 DoWork Arg 的Argument获取引用。

于 2012-11-16T17:41:25.980 回答
0

为了解决这个问题,你应该创建Form1引用而不是引用,Form因为Form没有textBox1字段但你Form1有,这是异常的来源,你应该改变这个:

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;
}
于 2012-11-16T18:03:02.810 回答