代码之家  ›  专栏  ›  技术社区  ›  Cristian Diaconescu

查找GUI控件的所有者线程

  •  2
  • Cristian Diaconescu  · 技术社区  · 16 年前

    在使用.NET应用程序时,我遇到了“cross-thread operation not valid”异常,只是它似乎发生在正确的线程中。 有没有办法找出哪个线程是创建了特定控件的线程?

    到目前为止我发现:

    一个有趣的时间与反射器上的屏幕 Control.Invoke(...) 方法使我转到user32.dll中的P/Invoke方法,该方法从窗口句柄获取线程Id:

    [DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
    public static extern int GetWindowThreadProcessId(HandleRef hWnd, out int lpdwProcessId);
    
    4 回复  |  直到 16 年前
        1
  •  3
  •   Allon Guralnek    16 年前

    我也遇到过同样的问题。即使从UI线程使用控件,我也会遇到这个异常。 InvokeRequired (或 Invoke )在 Handle 已创建控件的。这是一个托盘图标的上下文菜单,一些背景线程必须更改菜单项的值。如果用户从未打开上下文菜单,则从未创建句柄,控件也从未绑定到UI线程,随后将发生严重破坏。当这一切发生的时候 调用必需的 总是返回false和 只是在当前线程(不是UI线程)上运行了这个方法,所以 是在后台线程上创建的,控件永远绑定到该线程,就好像后台线程是它的UI线程一样。当试图使用UI线程的控件窗体时,抛出了一个跨线程异常。另一方面,如果用户在运行任何后台线程之前打开上下文菜单,一切都会正常工作。

    解决办法是打电话给 CreateControl() 方法,在任何后台线程有机会“窃取”控件并损坏线程所有权之前。

        2
  •  0
  •   rerun    16 年前

    在处理程序中创建事件时,是否可以捕获线程ID,并将其与获取异常时进行比较。这至少会告诉你,如果你是在同一线程。

        3
  •  0
  •   Nick    16 年前

    Control.BeginInvoke()对我来说总是很好。试试看。

        4
  •  0
  •   Pasi Savolainen    16 年前

    尝试使用Spy++应用程序,它与VS一起提供并向您显示窗口列表(大多数控件都是独立的子窗口)以及有关它们的一些信息。