内部控件上的"跨线程操作无效"异常

Nis*_*sim 7 c# multithreading winforms

我一直在努力解决这个问题:我有一个功能,旨在将控件添加到具有跨线程处理的面板,问题是尽管面板和控件在"InvokeRequired = false" - 我得到一个异常告诉我其中一个控件内部控件是从其创建的线程以外的线程访问的,该代码段如下所示:

public delegate void AddControlToPanelDlgt(Panel panel, Control ctrl);
    public void AddControlToPanel(Panel panel, Control ctrl)
    {
        if (panel.InvokeRequired)
        {
            panel.Invoke(new AddControlToPanelDlgt(AddControlToPanel),panel,ctrl);
            return;
        }
        if (ctrl.InvokeRequired)
        {
            ctrl.Invoke(new AddControlToPanelDlgt(AddControlToPanel),panel,ctrl);
            return;
        }
        panel.Controls.Add(ctrl); //<-- here is where the exception is raised
    }
Run Code Online (Sandbox Code Playgroud)

异常消息如下:

"跨线程操作无效:控制'pnlFoo'从其创建的线程以外的线程访问"

('pnlFoo'在ctrl.Controls下)

如何将ctrl添加到面板?!


当代码到达"panel.Controls.Add(ctrl);"时 line - panel和ctrl"InvokeRequired"属性设置为false,问题是ctrl中的控件将"InvokeRequired"设置为true.澄清事情:在基本线程上创建"panel",在新线程上创建"ctrl",因此,必须调用"panel"(导致"ctrl"再次需要调用).一旦完成两个调用,它就会到达panel.Controls.Add(ctrl)命令("panel"和"ctrl"都不需要在这种状态下调用)

这是完整程序的一小部分:

public class ucFoo : UserControl
{
    private Panel pnlFoo = new Panel();

    public ucFoo()
    {
        this.Controls.Add(pnlFoo);
    }
}

public class ucFoo2 : UserControl
{
    private Panel pnlFooContainer = new Panel();

    public ucFoo2()
    {
         this.Controls.Add(pnlFooContainer);
         Thread t = new Thread(new ThreadStart(AddFooControlToFooConatiner());
         t.Start()
    }

    private AddFooControlToFooConatiner()
    {
         ucFoo foo = new ucFoo();
         this.pnlFooContainer.Controls.Add(ucFoo); //<-- this is where the exception is raised
    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 3

在哪里pnlFoo创建,在哪个线程中创建?你知道它的句柄是什么时候被创建的吗?如果它是在原始(非 UI)线程中创建的,那就是问题所在。

同一窗口中的所有控制句柄应在同一线程上创建和访问。此时,您不需要两次检查是否需要 Invoke,因为ctrlpanel应该使用相同的线程。

如果这没有帮助,请提供一个简短但完整的程序来演示该问题。