多线程、访问UI控制

本文关键字:控制 UI 访问 多线程 | 更新日期: 2023-09-27 18:19:47

我有一个简单的应用程序,它有一个常见的UI线程和一个后台工作程序,在后台工作程序中我需要动态创建LinkLabels并将它们放置在FlowLayoutPanel中。为了做到这一点,我需要将LinkLabel的父级设置为FlowLayoutPanel。

这是我目前拥有的一段代码,然而,我在'l.Parent=panel;'行上得到了臭名昭著的"跨线程操作无效"

我对多线程操作还很陌生,但我认为调用是正确的,但显然不是。有什么建议吗?

LinkLabel l = new LinkLabel();
if (rssFeedPanel.InvokeRequired) {
    FlowLayoutPanel panel = null;
    rssFeedPanel.Invoke(new MethodInvoker(delegate { panel = rssFeedPanel; }));
    l.Parent = panel;
}
else
    l.Parent = rssFeedPanel;

多线程、访问UI控制

您需要在另一个线程上实际设置Parent属性。

LinkLabel l = new LinkLabel();
if (rssFeedPanel.InvokeRequired) {
    rssFeedPanel.Invoke(new MethodInvoker(delegate {
        l.Parent = rssFeedPanel;
    }));
}
else
    l.Parent = rssFeedPanel;

通常,几乎所有涉及访问UI控件成员的操作都只能从UI线程中完成。一些明显的例外是InvokeInvokeRequiredBeginInvokeBackgroundWorker类的一些方法。

如果您希望在这种情况下,也可以使用BeginInvoke而不是Invoke

我建议您将逻辑放在一个方法中,首先检查是否为InvokeRequired,然后在Invoke中调用该方法,否则直接调用它。

if (rssFeedPanel.InvokeRequired) {
    rssFeedPanel.Invoke(new MethodInvoker(delegate 
    { 
        AddLabel();
    }));
}
else AddLabel();

并将您的逻辑放入AddLabel方法:

private void AddLabel()
{
    LinkLabel l = new LinkLabel();
    l.Parent = rssFeedPanel;
}