从BackgroundWorker线程访问UI控件

Jam*_*ing 9 c# asynchronous udp winforms

我在Windows窗体上有一个调用RunWorkerAsync()方法的按钮,然后执行一个操作,然后更新同一窗体上的ListBox.

DoWork事件完成后,我为事件分配结果(这是一个列表),我处理RunWorkerCompleted()事件,然后执行以下代码来更新我的列表框

替代文字

这称之为:

替代文字

(道歉,代码格式化不起作用)

现在,当我运行应用程序并按下刷新按钮时,会出现以下异常:

替代文字

我怎么能绕过这个?

编辑:

在下面的语句中抛出异常,这发生在DoWork方法中,我清除内容以使列表保持最新;

listBoxServers.Items.Clear();

Tho*_*mar 13

您不能Invoke在列表框中调用,而是在表单上调用.对于WinForms应用程序,我使用类似于:

...
this.Invoke((MethodInvoker)delegate()
{
    // Do stuff on ANY control on the form.
});
...
Run Code Online (Sandbox Code Playgroud)

根据.NET版本,您可能必须为MethodInvoker自己声明委托

public delegate void MethodInvoker();
Run Code Online (Sandbox Code Playgroud)

但是,您也可以考虑使用ReportProgressBackground Worker 的功能.应该在表单的线程的上下文中调用相应的事件处理程序.


Nob*_*ody 11

这是一个我觉得非常方便的片段:

public static void ThreadSafe(Action action)
{
    Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, 
        new MethodInvoker(action));
}
Run Code Online (Sandbox Code Playgroud)

你可以传递任何Action类型的委托或简单地像这样的lambda:

ThreadSafe(() =>
{
    [your code here]
});
Run Code Online (Sandbox Code Playgroud)

要么

ThreadSafe(listBoxServers.Items.Clear);
Run Code Online (Sandbox Code Playgroud)

  • 确保项目中引用了"WindowsBase.dll".命名空间是`System.Windows.Threading`.http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.aspx (3认同)

Chr*_*way 9

每次你需要跨线程运行时,我所做的就是这样的事情:

listBoxServers.BeginInvoke(
    (Action)
    (() => listBoxServers.Items.Clear()));
Run Code Online (Sandbox Code Playgroud)