【问题标题】:Multi-threading, access UI control多线程,访问UI控件
【发布时间】:2012-01-07 19:32:47
【问题描述】:

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

这是我目前拥有的代码的 sn-p,但是,我在 '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;

【问题讨论】:

    标签: c# .net multithreading invoke invokerequired


    【解决方案1】:

    您需要在另一个线程上实际设置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

    【讨论】:

    • 只是好奇,您不能使用if (Dispatcher.Thread == Thread.CurrentThread) 并调用Dispatcher.BeginInvoke(new EventHandler<T>()) 来调用所有控件,而不是检查每个控件是否有InvokeRequired 吗?只是一个大脑放屁,但如果可以的话,我敢肯定它会快一点。 (是否需要你触发一个事件或其他东西并通过EventArgs 传递这些东西,但这很简单)
    • Dispatcher.Thread 是非静态的,因此您需要 UI 线程的实例。至于更快,我怀疑。通过查看代码,我敢打赌,如果创建了控制窗口,则大致相同。如果没有创建窗口,我敢打赌Control.InvokeRequired 会更快。
    【解决方案2】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 2015-06-02
      • 1970-01-01
      相关资源
      最近更新 更多