Как я не гарантирую повторно используемого доступа к своему серверу COM основного STA (C++)?

Хорошо, я подозреваю, что собираюсь испытать затруднения, даже помещая это в слова, так как мое понимание COM и квартир не действительно до задания ;-)

У меня есть незавершенный сервер/компонент COM (C++), который переносит некоторый унаследованный код. Из-за ограничений этого унаследованного кода я должен удостовериться, что методы COM-компонента:

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

Первые два я достиг путем регистрации сервера в ThreadingModel = "".

3-й является проблема, с которой я был удивлен даже встретиться.

Сервер используется многопоточным клиентом, который я не имею никакого контроля. Это создает несколько экземпляров сервера/компонента на различных потоках и называет их DoSomething () методом.

Это является ведущим к выбору зависания и катастрофического отказа поведения, и я видел, что отслеживания стека содержат два вызова к DoSomething () оба на потоке основного STA, но для различных экземпляров сервера.

Я первоначально даже не думал, что это было возможно, но у меня теперь есть частичное понимание, и я должен знать, может ли оно быть предотвращено.

Мое чтение предполагает, что я, возможно, должен использовать IMessageFilter некоторым способом, но я не уверен, является ли это чем-то, что может быть сделано на стороне сервера или должно быть сделано клиентом.

Кто-либо может помочь?

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

7
задан Tom Williams 16 February 2010 в 12:16
поделиться

3 ответа

Общее предотвращение повторного входа в целом может оказаться практически невозможным из-за способа реализации маршалинга COM, как уже описывал nobugz . Я предполагаю, что можно обнаружить его вручную или с помощью специальных «прокси» (см., Например, The Guts of the Universal Delegator Кейта Брауна).

Просто идея: если ваш COM-объект всегда должен работать в STA и вызывается только от клиентов, работающих в других квартирах (например, MTA), возможно, вы могли бы прочитать настраиваемый маршаллинг (предупреждение : Не для слабонервных). Поскольку у вашего унаследованного кода, похоже, нет никаких требований для работы в основной STA или, более конкретно, для взаимодействия с компонентами графического интерфейса, это может оказаться альтернативой.

3
ответ дан 7 December 2019 в 01:20
поделиться

COM маршалирует вызовы на ваш сервер через цикл сообщений. Вы можете попасть в ад повторного входа с помощью модального цикла COM. Этот цикл заботится об исходящих вызовах, которые необходимо маршалировать обратно в клиентский поток. Как события. Или звонки, сделанные вашим сервером, на другой сервер, который находится в другой квартире STA.Пока модальный цикл перекачивает сообщения, ожидая завершения исходящего вызова, он может принимать входящие вызовы, как и обычный цикл сообщений.

Технически повторный вход может также произойти, когда ваш сервер пытается поддерживать пользовательский интерфейс, перекачивая сообщения.

Да, это может быть очень трудным. Я не знаю какого-либо волшебного решения для этого, и я долго искал. Я также посмотрел на IMessageFilter и пришел к выводу, что решать эту проблему бесполезно.

5
ответ дан 7 December 2019 в 01:20
поделиться

То, что требуется, называется распределителем . Хороший обзор можно найти здесь: http://www.codeproject.com/KB/cpp/allocator.aspx

-121--4859466-

Я не думаю, что вы хотите Google Maps. Во-первых, условия использования не позволяют использовать только отображение вещей на карте Google на общедоступной веб-странице, во-вторых, существует другой API Google, который делает именно то, что вам нужно: Client location API: http://code.google.com/apis/ajax/documentation/#ClientLocation

Относительно «бизнеса»: Вы должны будете получить эти данные откуда-то - я не верю, что Google имеет сервис для этого. Возможно, вы могли бы просто использовать Google Search API и некоторую логику, чтобы найти только предприятия ( http://code.google.com/apis/ajaxsearch/ )

EDIT: Я для предприятий, возможно, вы могли бы взглянуть на этот образец: http://code.google.com/apis/ajaxsearch/samples.html # локальный поиск

-121--2583734-

Как nobugz точек out, это проблема из-за цикла сообщений.

Я бы, вероятно, посмотрел на решение этого вопроса внутри COM-объекта. Это зависит от сложности ваших вызовов, но вы можете рассмотреть возможность наличия рабочей очереди внутри COM-объекта, который обрабатывается одним потоком, находящимся под вашим контролем. Затем вы вручную упаковываете входные параметры в блок данных, который вы размещаете в очереди, ваш COM-вызов затем блокирует событие в вашей пользовательской структуре данных очередей «на вызов». Когда вызов обрабатывается в одном потоке, который обрабатывает вашу рабочую очередь, вы извлекаете параметры, делаете вызов, а затем упаковываете результат в пользовательскую структуру данных и устанавливаете событие... Ваш звонок теперь может распаковать вещи и вернуться.

Конечно, дьявол в деталях. Я бы лично использовал IOCP для построения пользовательской очереди, но это всего лишь деталь реализации.

Да, вы выполняете больше работы, но, учитывая ваши требования (один поток для выполнения всех вызовов и отсутствие повторного входа), это, вероятно, самый надежный способ сделать это. Затем вы можете, конечно, отменить требования STA для фактического COM-объекта сам, как вы сделали многопоточный объект, который может работать в любой квартире...

2
ответ дан 7 December 2019 в 01:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: