Требуется ли в этом случае петля сообщений STA?

У меня есть несколько COM-объектов, которые я создаю и запускаю в потоках в приложении.NET. Темы помечены как однопоточные квартиры, и все, кажется, работает. Насколько я понимаю, если эти потоки попытаются получить доступ к COM-объектам из основного потока, эти объекты будут автоматически маршалироваться и сериализироваться для меня в.NET, поэтому даже в этом случае все будет обрабатываться для меня, все безопасно и аккуратно, хотя, возможно, немного медленно

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

Я прочитал несколько советов о том, зачем нужен цикл сообщений (в основном из очень полезного Ханса Пассанта), и я понимаю, что цикл сообщений дает место в потоке A, где какой-то другой поток B может запросить COM-объекты живущих на нити А можно маршалировать и играть с ними. Если это правильно, то, пока никакие другие потоки не запрашивают что-либо из COM-объектов в потоке A, безопасен ли поток A, не перекачивая цикл сообщений? Или есть другие случаи, когда цикл сообщений мог бы также войти в игру?

Я здесь играю с огнем? И есть ли когда-нибудь случай, когда вы спрашиваете, играете ли вы с огнем, а нет?

2 ответа

Решение

Контракт STA требует прокачки цикла сообщений. Но да, это возможно сойти с не прокачки. Есть две основные вещи, которые могут пойти не так:

  • Любой вызов, который сделан на метод интерфейса из другой квартиры, включая другой поток STA или поток в MTA, не будет завершен. Это похоже на тупик в вашей программе, вызов просто никогда не возвращается. Помните, что вы можете контролировать свои собственные вызовы достаточно хорошо, но вы не знаете, что делает COM-компонент. Это может хорошо начать сам поток. Вы можете увидеть это в отладчике с Debug + Windows + Threads. Убедитесь, что вы запускаете отладчик в неуправляемом режиме и что вы можете учитывать все потоки, которые видите. Не особенно легко, кстати.

  • Многие многокомпонентные COM-компоненты рассчитаны на цикл обработки сообщений, отвечающий их потребностям. Это может быть что-то безобидное, как Таймер, он не будет работать, когда нет петли. Или это может сделать маршалинг внутри. Используйте Spy++ и проверьте, есть ли какие-либо скрытые окна, принадлежащие вашему новому потоку STA, и, если вы их видите, убедитесь, что есть проблемы. Диагноз - это просто недостойный компонент. Не поднимать события - обычная неудача.

Ничего особенного, чтобы пригвоздить к стене, если вы недостаточно знаете о внутренностях сервера. Обязательно проверь это.

Вызовы COM можно маршалировать без цикла сообщений.

Когда ваш поток STA ожидает чего-либо, он в большинстве случаев автоматически обрабатывает любые ожидающие COM-вызовы.

Документация для Thread.Join говорит Blocks the calling thread [...] while continuing to perform standard COM and SendMessage pumping.

То же самое происходит со многими другими функциями, вызываемыми от вашего имени (CoWaitForMultipleHandles и т. Д.), Например, когда ваш поток ожидает ввода-вывода.

Другие вопросы по тегам