Как определить, что вы находитесь в теме основного пользовательского интерфейса? (В CF) - PullRequest
1 голос
/ 05 мая 2009

Теперь, к сожалению, из-за того, что WinCE Usb Device Arrival / Removal устройства выставляет себя через WindowsMessages, я должен убедиться, что определенный (не-UI) компонент не создан в фоновом потоке. Я хотел бы подтвердить это с помощью исключения, но мне не хватает кода для подтверждения.

Этот компонент создает MessageWindow * и использует его для получения поступивших / удаленных сообщений usb. Проблема в том, что если кто-то создаст этот компонент в фоновом потоке (не обязательно; IsBackground = true), когда поток выйдет из окна, он будет уничтожен.

Есть идеи?

* в качестве отступления я все еще не знаю, почему Form не наследуется от этого класса

Обновление

Я думаю, что моя версия 1 была не очень ясной. Так что это v2.

Когда вы создаете MessageWindow или форму для этого вопроса в потоке, когда этот поток выходит из окна, форма / форма уничтожается.

Мой компонент создает «скрытое» окно сообщения для перехвата некоторых важных событий, поэтому я не хочу, чтобы оно было уничтожено. Поэтому я должен каким-то образом убедиться, что код, который создает форму, выполняется в потоке «Main UI».

Если возможно, я бы хотел избежать ссылки на «основную» форму этого компонента, так как он (архитектурно говоря) должен находиться в нескольких милях от пользовательского интерфейса.

Обновление

Перенос вопроса журнала в отдельную Q.

Ответы [ 5 ]

1 голос
/ 05 мая 2009

Хорошо, я понимаю, что вы не хотите, чтобы ваш компонент "знал" о главном окне - имеет смысл.

Как насчет этого: Как насчет того, чтобы убедиться, что вы всегда создаете экземпляр своего компонента в главном потоке? Ваш компонент создаст свое окно слушателя в потоке конструктора.

Если вы это сделаете, то вам просто нужно убедиться, что вы вызываете конструктор из основного потока. Я делаю некоторые предположения относительно вашего кода, но я предполагаю, что у вас должен быть какой-то класс в вашей архитектуре, который знает как о пользовательском интерфейсе, так и о вашем компоненте. Создайте там свой компонент, используя обратный вызов и методы InvokeRequired / Invoke главной формы.

0 голосов
/ 08 мая 2009

Привет! У меня была идея о вашей проблеме. Это просто случайная мысль, и я не знаю наверняка, сработает ли она (я не проверял и даже не компилировал это - мне просто показалось):

Что если вы получите дескриптор окна главного окна вашего приложения, а затем создадите вокруг него элемент управления (я предполагаю, что у вас есть приложение на основе gdi, такое как Winforms)?

этот код может не скомпилироваться, но он близок (он войдет в ваш компонент - обратите внимание, что для него потребуется приложение gdi windows / winform, а не консоль или приложение WPF).

Если вы попробуете это, я бы хотел узнать, сработало ли это для вас.


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...
}

0 голосов
/ 05 мая 2009

Почему бы не создать компонент без пользовательского интерфейса в фоновом потоке, а когда вы собираетесь обновить какой-либо компонент пользовательского интерфейса, просто посмотрите, есть ли invokeRequired, а затем вернитесь в основной поток, чтобы фактически выполнить обновление.

У вас не должно быть ничего, связывающего главный поток событий, IMO.

0 голосов
/ 05 мая 2009

Вы можете использовать его следующим образом:

void MyCallback()
{
if (form1.InvokeRequired) { // form1 is any existing gui control
    form1.Invoke(new Action<>(MyCallBack));
    return;
}
// your logic here
}
0 голосов
/ 05 мая 2009

В формах используется свойство InvokeRequired .

...