你怎么知道你是否在主UI线程上? (在CF中)

时间:2022-08-11 20:58:21

Now unfortunately due to the fact that WinCE Usb Device Arrival / Removal exposes itself via WindowsMessages I have to ensure that a certain (non-UI) component is not created on a background thread. I would like to assert this via an exception but am lacking the code for the assertion.

现在不幸的是,由于WinCE Usb设备到达/删除通过WindowsMessages暴露自己,我必须确保在后台线程上不创建某个(非UI)组件。我想通过异常断言,但缺少断言的代码。

This component creates a MessageWindow* and uses it to receive usb arrived/removed messages. The issue is if someone creates this component on a background thread (not necessarily; IsBackground = true) when the thread exits the window will be destroyed.

该组件创建MessageWindow *并使用它来接收usb到达/删除的消息。问题是如果有人在后台线程上创建此组件(不一定; IsBackground = true),当线程退出窗口时将被销毁。

Any ideas?

*as an aside I still don't know why Form doesn't inherit from this class

*作为一个旁边我仍然不知道为什么Form不从这个类继承

Update

I think my version 1 wasn't very clear. So this is v2.

我认为我的第1版不太清楚。所以这是v2。

When you create a MessageWindow or a Form for that matter on a thread, when that thread exits the Window/Form is destroyed.

当您在线程上为该事项创建MessageWindow或Form时,该线程退出Window / Form时将被销毁。

My component is creating a "hidden" message window to intercept some important events, ergo I do not wish for it to be destroyed. Therefore I must somehow ensure that the code that creates the form is running on the "Main UI" thread.

我的组件正在创建一个“隐藏”消息窗口来拦截一些重要事件,因为我不希望它被销毁。因此,我必须以某种方式确保创建表单的代码在“主UI”线程上运行。

If possible i'd like to avoid passing down a reference to the "main" form to this component as it is (architecturally speaking) supposed to be miles away from the UI.

如果可能的话,我想避免将对“主”表单的引用传递给该组件,因为它(在架构上讲)应该距离UI几英里远。

Update

Moving logging question to a separate Q.

将记录问题移到单独的Q.

5 个解决方案

#1


Ok, I understand that you don't want for your component to "know" about the main window -- makes sense.

好的,我知道你不希望你的组件“知道”主窗口 - 这是有道理的。

How about this: How about if you make sure that you always instance your component on the main thread? You component will create it's listener window on the constructor's thread.

怎么样:如果你确定你总是在主线程上实例化组件怎么样?您组件将在构造函数的线程上创建它的侦听器窗口。

If you do that, then you just need to make sure that you call the constructor from the main thread. I'm making some assumptions about your code, but I'm guessing that you must have some class in your architecture that knows about both the UI and your component. Create your component there, using a callback, and the main form's InvokeRequired/Invoke methods.

如果你这样做,那么你只需要确保从主线程调用构造函数。我对你的代码做了一些假设,但我猜你必须在你的架构中有一些知道UI和你的组件的类。使用回调和主窗体的InvokeRequired / Invoke方法在那里创建组件。

#2


In forms, you use the InvokeRequired property.

在表单中,您使用InvokeRequired属性。

#3


Why not create the non-UI component on a background thread and when you go to update any UI component just look to see if invokeRequired then get back on the main thread to actually do the update.

为什么不在后台线程上创建非UI组件,当你去更新任何UI组件时,只需查看invokeRequired然后返回主线程以实际进行更新。

You should have nothing really tying up the main event thread, IMO.

你应该没有什么真正占用主要事件线程,IMO。

#4


You can use it in this way:

您可以这样使用它:

void MyCallback()
{
if (form1.InvokeRequired) { // form1 is any existing gui control
    form1.Invoke(new Action<>(MyCallBack));
    return;
}
// your logic here
}

#5


Hey there: I had an idea about your problem. This is just a random thought, and I don't know for sure whether it will work (I have not tested, nor even compiled this -- it just hit me):

嘿那里:我对你的问题有所了解。这只是一个随意的想法,我不确定它是否会起作用(我没有测试过,甚至没有编译过它 - 它只是打我):

What if you get the window handle of the main window of your app, then build a Control around it (I'm assuming that you have a gdi-based app, like Winforms)?

如果您获得应用程序主窗口的窗口句柄,然后围绕它构建一个控件(我假设您有一个基于gdi的应用程序,如Winforms),该怎么办?

this code might not compile, but it's close (it would go into your component -- note that it would make your component require a gdi windows/winform app, as opposed to a console or WPF app).

这段代码可能无法编译,但它很接近(它会进入你的组件 - 注意它会使你的组件需要一个gdi windows / winform应用程序,而不是控制台或WPF应用程序)。

If you do try it, I'd love to hear whether it worked for you.

如果您尝试过,我很想知道它是否适合您。


using System.Diagnostics;
using System.Windows.Forms;
void Init()
{
   // get handle to the main window
   intPtr mainWindowHandle = Process.GetCurrentProcess().MainWindowHandle;
   Control mainWindow = Control.FromHandle(mainWindowHandle);
   if(mainWindow.InvokeRequired)
      mainWindow.Invoke(SetupMessageWindow);
   else
      SetupMessageWindow();
}
void SetupMessageWindow()
{
  // do your thing...
}

#1


Ok, I understand that you don't want for your component to "know" about the main window -- makes sense.

好的,我知道你不希望你的组件“知道”主窗口 - 这是有道理的。

How about this: How about if you make sure that you always instance your component on the main thread? You component will create it's listener window on the constructor's thread.

怎么样:如果你确定你总是在主线程上实例化组件怎么样?您组件将在构造函数的线程上创建它的侦听器窗口。

If you do that, then you just need to make sure that you call the constructor from the main thread. I'm making some assumptions about your code, but I'm guessing that you must have some class in your architecture that knows about both the UI and your component. Create your component there, using a callback, and the main form's InvokeRequired/Invoke methods.

如果你这样做,那么你只需要确保从主线程调用构造函数。我对你的代码做了一些假设,但我猜你必须在你的架构中有一些知道UI和你的组件的类。使用回调和主窗体的InvokeRequired / Invoke方法在那里创建组件。

#2


In forms, you use the InvokeRequired property.

在表单中,您使用InvokeRequired属性。

#3


Why not create the non-UI component on a background thread and when you go to update any UI component just look to see if invokeRequired then get back on the main thread to actually do the update.

为什么不在后台线程上创建非UI组件,当你去更新任何UI组件时,只需查看invokeRequired然后返回主线程以实际进行更新。

You should have nothing really tying up the main event thread, IMO.

你应该没有什么真正占用主要事件线程,IMO。

#4


You can use it in this way:

您可以这样使用它:

void MyCallback()
{
if (form1.InvokeRequired) { // form1 is any existing gui control
    form1.Invoke(new Action<>(MyCallBack));
    return;
}
// your logic here
}

#5


Hey there: I had an idea about your problem. This is just a random thought, and I don't know for sure whether it will work (I have not tested, nor even compiled this -- it just hit me):

嘿那里:我对你的问题有所了解。这只是一个随意的想法,我不确定它是否会起作用(我没有测试过,甚至没有编译过它 - 它只是打我):

What if you get the window handle of the main window of your app, then build a Control around it (I'm assuming that you have a gdi-based app, like Winforms)?

如果您获得应用程序主窗口的窗口句柄,然后围绕它构建一个控件(我假设您有一个基于gdi的应用程序,如Winforms),该怎么办?

this code might not compile, but it's close (it would go into your component -- note that it would make your component require a gdi windows/winform app, as opposed to a console or WPF app).

这段代码可能无法编译,但它很接近(它会进入你的组件 - 注意它会使你的组件需要一个gdi windows / winform应用程序,而不是控制台或WPF应用程序)。

If you do try it, I'd love to hear whether it worked for you.

如果您尝试过,我很想知道它是否适合您。


using System.Diagnostics;
using System.Windows.Forms;
void Init()
{
   // get handle to the main window
   intPtr mainWindowHandle = Process.GetCurrentProcess().MainWindowHandle;
   Control mainWindow = Control.FromHandle(mainWindowHandle);
   if(mainWindow.InvokeRequired)
      mainWindow.Invoke(SetupMessageWindow);
   else
      SetupMessageWindow();
}
void SetupMessageWindow()
{
  // do your thing...
}