如何使用BackgroundWorker确保UI响应

Gra*_*ton 5 c# backgroundworker winforms

BackgroundWorker在c#中是否安全?

我问这个的原因是因为我得到了一个

在一个线程上创建的控件不能作为另一个线程上的控件的父级

它的例外.这是我的DoWork事件代码:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{



    var openFile = document.Open(MyFileName);
    e.Result = openFile;
}
Run Code Online (Sandbox Code Playgroud)

其中document是在创建父窗体时初始化的UI控件.在Open方法期间,document将填充各种属性.

我试图更改代码以调用,但同样的问题仍然存在.即

document.GetType().GetMethod("Open)".Invoke(document, new object[]{MyFileName})
Run Code Online (Sandbox Code Playgroud)

将产生与上述相同的错误.

知道如何操纵document控件吗?换句话说,如何使上面的代码工作?

编辑:有人建议我使用Control.Invoke,但它仍然无效(两个线程都被绞死).这是我试过的代码:

private delegate bool OpenFile(string filePath);
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{



    OpenFile oF = new OpenFile(document.Open);
    var openFile = Invoke(oF, MyFileName);  // it doesn't really matter whether I use BeginInvoke or Invoke, or other Control.Invoke, the end result is the same. Both the main thread hosting the document and the thread that launches the UI hanged.

    e.Result = openFile;
}
Run Code Online (Sandbox Code Playgroud)

Gra*_*meF 5

这不是线程的问题,而是它试图在UI控件上调用方法.在WPF和WinForms中,控件只能在UI线程上调用(通常有一个).你没有说你正在使用哪个,但你需要调用Control.InvokeWinForms或Dispatcher.InvokeWPF 的方法.

Invoke()您显示的反射方法实际上将在当前线程上调用该方法.


Meh*_*ari 1

虽然我不清楚 a 的线程安全性到底是什么意思BackgroundWorker,但问题不在于该对象;而是在于该对象。Windows 窗体控件设计为在单个线程(UI 线程)上进行操作。您不应在不同线程上操作 Windows 窗体对象。您可以使用该Control.Invoke方法从其他线程调用UI线程中的操作(Invoke您当前使用的方法是通过反射提供的,与此问题完全无关):

Invoke(new Action(MethodToRunInUIThread));

void MethodToRunInUIThread() {
    // do stuff here.
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果您所做的只是操作 UI 对象,那么使用后台工作程序就没有意义。