Есть ли причина, по которой настройка управляемого клиента .NET на использование потоков STA может вызвать проблемы с исключениями на собственном COM-сервере? - PullRequest
5 голосов
/ 09 марта 2012

У меня есть собственный (Delphi) COM-сервер, который объявлен как STA (Apartment Threaded Model).

Он содержит несколько алгоритмов, которые в некоторых случаях генерируют исключения переполнения. Эти исключения обрабатываются в коде, и все работает как надо, если я получаю доступ к COM-серверу с клиента в главном потоке.

Если клиент является нативным (Delphi), я могу получить доступ к серверу из нескольких потоков, если придерживаюсь правила, согласно которому объект, созданный в потоке, выполняет все свои вызовы методов из этого же потока.

Однако, если клиент является управляемым клиентом (проверено на Vb.NET и C #), если я установил ApartmentState потоков клиента на MTA, все работает нормально, но я получаю снижение производительности.

Этого я ожидаю, так как я полагаю, что COM должен делать некоторые покерные игры (то есть маршалинг), чтобы все были довольны.

Однако, если я изменю ApartmentState на STA и, таким образом, обеспечу прямое соединение между клиентом и сервером, клиент потерпит крах с ошибкой, обычно System.stackoverflowexception в CustomMarshallers.dll.

Если я устраню числа, вызывающие эти переполнения, у меня нет проблем.

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

1 Ответ

0 голосов
/ 26 марта 2012

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

Теоретически возможно, что различное доступное пространство стека между STA иСлучаи MTA будут иметь значение для стека боров приложения Delphi.Но следующая вероятность более вероятна.

StackOverflowException, вероятно, вызвано самой стороной Delphi (предположим, что сообщение об ошибке называет его «необработанным»).Посмотрите подробнее на все механизмы обработки ошибок на стороне Delphi и посмотрите, какие механизмы могут привести к рекурсии именно на ошибках.Например, код, выполняемый для определенного события, может содержать защищенный блок, в котором предложение catch делает что-то, вызывающее то же событие.

Я полагаю, что разница, которую вы видите в STA по сравнению с MTA, несколько сгладится, если выудалите PreserveSigAttribute из клиентского кода, чтобы исключение переполнения стека перестало переводиться в HRESULT, который ваш клиент предположительно игнорирует прямо сейчас.(Если вы использовали tlbimp.exe, этот атрибут был указан неявно. Это означает, что вы хотите обрабатывать исключения как путь COM как возвращаемые значения, а не как путь .NET как исключения.)

...