代码之家  ›  专栏  ›  技术社区  ›  user153498

C#-是否可以在单独的线程中安全地拥有一个拥有的窗体?

  •  4
  • user153498  · 技术社区  · 14 年前

    我正试图为一个用C#编写的应用程序编写一个专用的屏幕键盘(OSK)。为了方便起见,我创建了一个表单,表单上有几个表示键的按钮,单击这些按钮可以调用 SendKeys 并发出相应的钥匙。

    Owner 财产。这样,每当用户聚焦应用程序时,OSK就会弹出,如果它说主窗口被拖到它上面,它就会停留在主窗口的顶部。

    这一切都很好,但因为我有模态对话框,我也想与OSK一起使用,我试图在一个单独的线程中创建它,完成它自己的消息循环(通过 Application.Run )因此,它仍然可以用于主线程中的任何模态对话框。

    InvalidOperationException 因为跨线程调用。一个具体的例子是调用 Application.Run(osk) 在新线程中,会发生一个跨线程错误,因为它正试图用所有者(主窗口)更新窗口的句柄。

    我的问题是,有没有可能在一个线程上以一种安全的方式拥有一个独立于所有者的窗体?如果不能做到这一点,是否有可能模仿一个拥有的表单的特性(即只在主窗口中始终处于顶部,并且在主窗口聚焦时弹出)?

    4 回复  |  直到 14 年前
        1
  •  1
  •   Hans Passant    14 年前

    好吧,把问题推出来试试。套Control.CheckForIllegalCrossThreadCalls控件在设置所有者之前设置为false,之后设置为true。测试一下。如果遇到问题,请直接尝试pinvoking SetParent(),而不是设置所有者。Windows窗体实际上使用SetWindowLongPtr,这是SDK不推荐的。

        2
  •  1
  •   YWE    14 年前

    我要试试这个。尝试将OSK作为单独的进程运行。

        3
  •  1
  •   configurator    14 年前

    尝试使用 ShowDialog 对于OSK也是如此,而不是 Application.Run - 显示对话框

    new Thread(() => new OSK().ShowDialog());
    
        4
  •  0
  •   Cheng Chen    14 年前

    为什么不用 Control.Invoke 进行跨线程调用以避免 InvalidOperationException