多线程,访问UI控件

时间:2012-01-07 19:32:47

标签: c# .net multithreading invoke invokerequired

我有一个简单的应用程序,通常的UI线程和后台工作者,在后台工作器中我需要动态创建LinkLabel并将它们放在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;

2 个答案:

答案 0 :(得分:3)

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

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

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

如果您希望遇到这种情况,也可以使用BeginInvoke代替Invoke

答案 1 :(得分:3)

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

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

并将您的逻辑放在AddLabel方法中:

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