3

我有一个简单的应用程序,带有通常的 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;
4

2 回答 2

3

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

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

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

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

于 2012-01-07T19:34:21.943 回答
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;
}
于 2012-01-07T19:39:44.920 回答