Re[2]: SEHException при вызове метода COM-объекта из другой
От:
Аноним
Дата:
08.10.10 08:35
Оценка:
Здравствуйте, Jolly Roger, Вы писали:
JR>Здравствуйте, apilikov, Вы писали:
JR>Коротко говоря, Вы нарушаете требования апартаментной модели COM. Вы создаёте "ядро" в STA апартаменте главного потока, а вызываете метод в другом потоке, входящем в другой апартамент. При таком подходе проблемы с SetErrorInfo — не единственная, которая может Вас ожидать. Простейшее решение — создавать объект "ядра" в доп. потоке — члене MTA и использовать его только из потоков — членов MTA.
JR>PS Постарайтесь всё-таки расставлять запятые, иначе Ваш текст тяжело читать.
насчет запятых постараюсь учесть.
что касается вашего поста, то не очень понятно что именно я нарушаю.
когда я передаю указатель на COM объект в другую нить, то при вызове из другой нити вызов пойдет через прокси, т.е. будет выполнен маршаллинг и код ядра все равно будет исполнен в том потоке который создал объект. Так работает COM. И в этом состоит смысл STA который у меня используется.
И я кстати разобрался с причиной появления у меня SEHException и сейчас заодно изложу вам в чем же там было дело.
Суть в том что из "ядра" я вызывал функцию некоторой DLL-ки. Это просто WIN32 библиотека с экспортируемыми функциями в стиле C.
Из этой DLL-ки собственно и вызывалась функция "сервера". Я опустил этот момент когда описывал проблему потому что посчитал ее несущественной. Теперь же я понимаю что этот момент был ключевым, приношу извинения.
Фишка в том что когда я возбуждал ошибку в "сервере" она приходила в DLL в виде _com_error, но я не ловил ее в DLL-ке а передавал сразу в "ядро" где у меня был написан соответствующий catch. Так вот в Windows есть такая фигня как контекст активации. И у этих контекстов есть определенный порядок. Так вот если из DLL-ки выбросить исключение за ее пределы, то в catch который находится в ядре будет словлено исключение. Все вроде бы хорошо, однако после того как COM-вызов будет завершен и я выйду из кода "ядра" Windows захочет деактивировать контекст активации и учитывая что я грубо вышел из кода DLL-ки деактивируемый контекст активации не будет являться последним активированным контекстом. Есть даже специальное WIN32 исключение которое именно так и называется и имеет код 0xC0150010.
Так вот при выходе из кода "ядра" Windows генерировала это исключение, которое в свою очередь .NET не знала как смапить, ну т.е. на какое исключение из ее набора, смапить это исключение и в итоге мапила его на SEHException.
После того как я сделал обработку исключений непосредственно в DLL все сразу заработало корректно.
Вызовы из другой нити прекрасно проходят в ту нить которая создала объект, потом я вбрасываю исключение и корректно получаю его во второй нити.
Так что вот такая вещь, век живи век учись.