Потоки, ком + звонки с SendMessage сообщениями - PullRequest
6 голосов
/ 19 марта 2012

У меня есть приложение, которое создает поток, который общается с основным пользовательским интерфейсом через сообщения Windows.Он просто отправляет сообщение в основной поток приложения и получает статус.

Таким образом, я отображаю модальные окна и занимаюсь другими делами.

Проблема в том, что мне нужно отобразить форму, котораязвонит на com + сервер.Таким образом я получаю ошибку OLE 8001010D: исходящий вызов не может быть выполнен, так как приложение отправляет входной синхронный вызов.

Я думаю, что это происходит, потому что используется основной SendMessage, а вызовы com + требуют сообщений Windows для своих задач.

Во всяком случае, в Delphi я не могу отобразить форму из потока, но как я могу обойти проблему ...?

Спасибо

РЕДАКТИРОВАТЬ:

  1. MAIN (UI) 2. РЕЗЬБА

A.Поток (2) отправляет сообщение в основной поток (1) B. Основной поток (1) получает сообщение и, прежде чем позволить ему вернуться в поток, отображает окно.C. Модальное окно в главном потоке хочет сделать вызов com +, возникает вышеуказанная ошибка.


  1. В каком потоке находится модальное окно?2. Из какого потока идет COM-вызов?3. В каком потоке был создан экземпляр COM-объекта?4. Фоновый поток инициализируется STA?5. Показывается ли модальная форма из обработчика SendMessage?- Роман Р. 2 минуты назад

    1. MAIN
    2. MAIN
    3. MAIN
    4. CoInitializeEx (ноль, COINIT_MULTITHREADED);
    5. да.

1 Ответ

12 голосов
/ 19 марта 2012

Причиной проблемы является неспособность COM упорядочить исходящий вызов COM при обработке запроса SendMessage. Появляющаяся ошибка RPC_E_CANTCALLOUT_ININPUTSYNCCALL (0x8001010D), на которую вы ссылаетесь. У меня сложилось впечатление, что это относится только к вызовам SendMessage, которые являются частью входящих межпоточных COM-запросов, однако это могло быть ложным предположением.

Типичным обходным решением будет заменить SendMessage на PostMessage с последующим ожиданием объекта синхронизации, события или семафора. Таким образом, фоновый поток вашего вызывающего абонента не удерживает сообщения для синхронизации вызовов и автономно ожидает, в основном потоке сообщение отправляется через обычную очередь сообщений и в конечном итоге достигает того же обработчика.

В качестве бонуса у вас есть возможность безопасно прекратить фоновую ветку. Если в настоящее время он блокируется API-интерфейсом SendMessage, ожидающим модальное диалоговое окно, предлагаемое изменение позволит вам сигнализировать объект синхронизации из основного потока и продолжать его работу, например. если вы хотите безопасно прекратить его.

Альтернативное решение может состоять в том, чтобы вызвать функцию InSendMessage, а если true - отложить модальный интерфейс, например, снова отправив сообщение самому себе, чтобы позже всплыть в другом обработчике сообщений.

...