Как я могу обрабатывать оконные сообщения из отдельного потока? - PullRequest
6 голосов
/ 26 декабря 2009

Я хочу запустить отдельный поток для обработки оконных сообщений (через блокирующий цикл GetMessage), но впоследствии все равно создаю окна в начальном потоке.

В отдельном потоке, как только он запускается, я звоню PeekMessage с PM_NOREMOVE, чтобы убедиться, что очередь сообщений существует (это необходимо?), А затем ..

AttachThreadInput(initial thread id,GetCurrentThreadId(),true)

.. прежде чем наконец войти в цикл сообщений

Я пока не использую мьютекс или cs, чтобы гарантировать, что это происходит вовремя, но просто для простоты использую оператор Sleep в моем начальном потоке.

Несмотря на это, оконные сообщения не перехватываются отдельным потоком.

Я немного не уверен относительно того, правильно ли я делаю это, и был бы признателен за любое возможное руководство. Оба потока находятся в одном процессе

Спасибо всем

Ответы [ 2 ]

7 голосов
/ 26 декабря 2009

Это не то, что делает AttachThreadInput. Даже после того, как вы подключили свою очередь ввода к другому потоку, Windows все еще имеет сходство потоков. Сообщения в очереди для данного окна могут быть удалены из очереди только потоком этого окна.

Что делает AttachTheadInput, так это заставляет два потока совместно использовать очередь ввода. Это позволяет им запрашивать информацию о состоянии ввода и знать, что другой поток получит тот же ответ для того же запроса. Например, один поток может вызвать GetAsyncKeyState и знать, что ответ отражает состояние ключа для другого потока.

Это позволяет двум или более потокам иметь одинаковое отношение к входной очереди и друг к другу, как процессы имели в Windows 3x. Это причина того, что этот API существует; так что сложные многопроцессорные приложения могут быть портированы с Win 3x на Win95 / WinNT.

2 голосов
/ 27 декабря 2009

Кажется, лучший способ инициировать создание окна из основного потока, в то время как обработка сообщений для них в отдельном циклическом потоке - это использование настраиваемого сообщения, которое может быть отправлено в отдельный поток. окно, но все же позволяющее вызывать это действие из исходного потока:

1) Выделите пользовательское сообщение и создайте структуру для хранения параметров инициализации окна:

message_create_window = WM_USER + 0;
class Message_create_window{
    Message_create_window(...);
};

2) Вместо вызова CreateWindow (Ex) используйте что-то похожее на следующее, передавая параметры создания соответствующего окна:

PostThreadMessage(
    thread.id,
    message_create_window,
    new Message_create_window(...),
    0
);

3) Обработайте пользовательское сообщение в насосе сообщений вашей цепочки обработки пользовательского интерфейса, извлеките параметры создания, а затем освободите:

MSG msg;
GetMessage(&msg,0,0,0);
...
switch(msg->message){
    ...
    case message_create_window:{
        Message_create_window *data=msg->wParam;
        CreateWindowEx(data->...);
        delete data;
    }break;
    ...

Это, однако, имеет следующие побочные эффекты:

  • Окно будет создано асинхронно. Если требуется, чтобы начальный блок потока до тех пор, пока не было создано окно (или, действительно, существование окна когда-либо может быть подтверждено), то должен использоваться инструмент синхронизации потока (такой как событие)
  • Следует соблюдать осторожность при взаимодействии с окном (в конце концов, это многопоточное приложение)

Если в этом ответе есть серьезные пробелы или это кажется ужасным подходом, пожалуйста, исправьте меня. (Это все еще мой вопрос, и я пытаюсь найти лучший способ сделать это)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...