2012-05-18 4 views
2

У меня есть COM-объекты, которые я создаю и работаю в потоках в приложении .NET. Потоки отмечены как Single Threaded Apartments, и все, кажется, работает. Я понимаю, что если эти потоки попытаются получить доступ к COM-объектам из основного потока, тогда эти объекты будут автоматически маршалированы и сериализованы для меня в .NET, поэтому даже в этом случае все будет обработано для меня, все безопасно и аккуратно, хотя возможно немного медленно.Требуется ли сообщение STA Message Loop в этом случае?

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

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

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

+0

У вас есть события? У вас есть контроль над обработчиками событий, чтобы убедиться, что их повторные вызовы не вызовут бесконечной рекурсии? Сообщение об отправке обычно используется для разрыва этого цикла, если у вас есть насос сообщений. –

+0

Думаю, я не знаю о проблемах, связанных с этим. Что могло бы вызвать событие в потоке, который я создал, и никто больше не смотрит? Объекты COM, которые я использую? Насколько я знаю, они не создают каких-либо событий ... – user12861

+0

Вы реализуете интерфейсы исходящих событий, такие как IConnectionPointContainer, если дизайн вашего COM-объекта включает в себя уведомление внешнего мира о том, что происходит. –

ответ

3

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

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

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

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

+0

Проницательный ответ как всегда. Очень признателен. – user12861

+0

Я думаю, у нас была аналогичная проблема с COM-объектом CDO.Message. Он никогда не возвращался из 'Send()', когда пользователь сильно перемещал окна MDI. Вероятно, потому, что он полагался на очередь сообщений, как сказал, и не мог опубликовать в нем сообщение, так как он был заполнен из всех перемещений окна, а реализация забыла проверить, что 'PostMessage' потерпел неудачу. –

1

COM-вызовы могут быть маршалированы без контура сообщения.

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

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

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

+0

Хорошая точка. Спасибо за совет. – user12861

 Смежные вопросы

  • Нет связанных вопросов^_^