Я наткнулся на то, что на первый взгляд выглядит как проблема с MT, но я пытаюсь подробно разобраться в модели STA, используемой COM +.
Фактически, у меня есть устаревший компонент COM +, написанный на VB6, который обращается к собственной (то есть не-COM) Win32 DLL, написанной на C ++.
Имея некоторые прерывистые (и невозможные воспроизвести при тестировании) проблемы с ним, я добавил отладочный код, чтобы узнать, что происходит, и обнаружил, что, когда возникают проблемы, у меня были сообщения журнала, чередующиеся в файле, поэтому это означало, что DLL вызывается сразу двумя потоками.
Теперь ведение журнала ведется в файл для каждого потока на основе _getpid () и GetCurrentThreadId (), поэтому кажется, что когда вызывается код в C ++ DLL, он вызывается дважды в одном потоке в одно и то же время. Насколько я понимаю, STA говорит, что это могло быть так, поскольку COM маршалирует отдельные экземпляры объектов в один поток, приостанавливает и возобновляет выполнение по желанию.
К сожалению, я не знаю, что делать дальше. Я читаю, что мне следует вызвать CoInitialiseEx () в DllMain (), чтобы сообщить COM, что это STA DLL, но в других местах говорят, что это действительно только для COM-DLL и не будет иметь никакого эффекта в собственной DLL. Единственный другой вариант - обернуть части DLL в критические разделы для сериализации доступа (принимая любое снижение производительности, которое оказывает на подбородок).
Я мог бы попытаться переработать DLL, но нет общего состояния или глобальных переменных - все находится в локальных переменных, поэтому теоретически каждый вызов должен иметь свой собственный стек, но мне интересно, оказывает ли модель STA в основном какое-то странное влияние на это и просто повторно войти в уже загруженную DLL в той же точке входа, что и другой вызов. К сожалению, я не знаю, как подтвердить или проверить эту теорию.
Вопросы в основном таковы:
- Когда компонент STA COM + вызывает собственную DLL, в модели STA нет ничего, что могло бы предотвратить приостановку активного «потока» и передачу управления другому «потоку» в середине вызова DLL?
- Подходит ли CoInitialiseEx () для решения этой проблемы или нет?
- Если ни (1), ни (2) не являются «хорошими» предположениями, что происходит?