Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: ActiveX/СОМ/CORBA > COM сервер для контроля потоков приложения.


Автор: Чучмек 8.4.2011, 14:21
Для контроля состояния потоков приложения, достаточно  на каждый поток созать ProgressBar. 
Однако,каждая запущенная копия приложения имеет свое окно,что не совсем (или совсем не) удобно.
Одним из возможных решений является создание COM сервера, в виде exe. А в каждом потоке инициализировать интерфейс сервера.
Вопрос.
1. Требуется ли дополнительная синхронизация при вызове методов COM сервера из потоков/приложений?
2. Как отменить закрытие COM сервера,после закрытия всех приложений подключаемых к нему?

Автор: cat512 9.4.2011, 11:46
из такого описания мало что понятно! Например что такое
Цитата

дополнительная синхронизация

?
Цитата

из потоков/приложений

Эти "потоки приложения " где конкурируют? На клиенте или на сервере?
Архитектуру можно построить разными способами. За это отвечает параметр 
"threading model" STA сериализует вызовы серверу. MTA, Free and Both - требуют синхронизации.
Причём этот параметр актуален только для in-proc серверов. Если потоки создаются и конкурируют на out-proc сервере, то в этом случае необходима синхронизация.
Цитата

Как отменить закрытие COM сервера

Имеется ввиду уничтожение? Если да, то время жизни Com-объектов, контролируется механизмом подсчёта ссылок. Отсюда следствие, при иниц. сервера, хранить лишнюю ссылку на объект

Автор: Чучмек 13.4.2011, 23:59
Цитата(cat512 @  9.4.2011,  11:46 Найти цитируемый пост)
На клиенте или на сервере

На сервере. 
Например: 
Поток вызывает метод сервера setProgress(Hthread,Hprocess,Percent);
Куда передает дескриптор потока,процесса и степень выполнения.

На сервере  setProgress  заносит эти параметры в структуру вида:
Код

type
TThreadProgressRec=record
size:cardinal;
mThreadProgress:array[0..maxlength-1] of TThreadProgress;
end;
TThreadProgress=record
Hthread:type1;
Hprocess:type2;
Percent:type3;
end;

увеличивая ThreadProgressRec.size
Основной поток сервера, по таймеру,  извлекает данные из структуры ThreadProgressRec и обновляет отображаемую информацию.
Понятно, что проблема синхронизации решается вызовом  EnterCriticalSection/LeaveCriticalSection.

Цитата(cat512 @  9.4.2011,  11:46 Найти цитируемый пост)
"threading model" STA сериализует вызовы серверу. MTA, Free and Both - требуют синхронизации.

По умолчанию, если не ошибаюсь (нет дельфей под руками), идет multithreaded apartment model.?.?
И от этого??? параметра зависит- создается один, общий, COM обьект для всех вызовов или для каждого свой.???

Цитата(cat512 @  9.4.2011,  11:46 Найти цитируемый пост)
 Отсюда следствие, при иниц. сервера, хранить лишнюю ссылку на объект

Код

var obj:TmyCOMobject;

procedure TmyCOMobject.setProgress(Hthread:type1;Hprocess:type2,Percent:type3);
begin
if obj=nil then
  begin
  obj:=self;
  self._AddRef;
  end;
......
end;

//При закрытии  сервера
.....
if obj<>nil then obj._Release;
.....
.....
.....

Так чтоли? Однако это, помоему, через Ж.
Есть ли, хотябы, способ отлавливать(на сервере) создание COMobject

Автор: cat512 14.4.2011, 20:40
Цитата

По умолчанию, если не ошибаюсь (нет дельфей под руками), идет multithreaded apartment model.?.?
И от этого??? параметра зависит- создается один, общий, COM обьект для всех вызовов или для каждого свой.???

Нет не так.
То что ты описал, зависит от двух параметров Threading model и Instancing.
Instancing - определяет, как будут обрабатываться вызовы клиентов (одним общим объектом или отдельным для каж. вызова)
Threading model - определяет, будут ли доступны и каким образом, объекты сервера в многопоточной среде.

Цитата

Так чтоли? Однако это, помоему, через Ж

Как абстрактно был задан вопрос, такой ответ на него ты и получил!
Если есть воображение, то не вижу проблемы сделать это по другому. Например реализовать свой протокол освобождения объектов, между клиентом и сервером, или например реализовать некий диспетчер, который будет перехватывать вызовы на уничтожения объекта.  
Цитата

Есть ли, хотябы, способ отлавливать(на сервере) создание COMobject

Конечно же есть.  При создании объекта, всегда вызывается метод Initialize. Думаю дальше сам догадаешься что делать



Автор: Чучмек 16.4.2011, 00:04
Цитата(cat512 @  14.4.2011,  20:40 Найти цитируемый пост)
метод Initialize

ага нашел, override.
А для завершения - переопределить destroy.?

Автор: cat512 16.4.2011, 17:01
Цитата(Чучмек @ 16.4.2011,  00:04)
Цитата(cat512 @  14.4.2011,  20:40 Найти цитируемый пост)
метод Initialize

ага нашел, override.
А для завершения - переопределить destroy.?

да, перекрываешь destroy и радуешься жизни  smile 

Автор: Чучмек 29.5.2011, 16:56
  • Цитата(Чучмек @  8.4.2011,  14:21 Найти цитируемый пост)
    Как отменить закрытие COM сервера,после закрытия всех приложений подключаемых к нему

    Проще всего,как оказалось, создать экземпляр com объекта внутри  самого COM сервера.При запуске.


  • Использовать com в потоках, да еще если потоки в dll, оказалось проблематично.
    Это связанно, в первую очередь, с необходимостью вызова coInitialize/coUnInitialize.

    Отступая, хочу сказать,что пока есть подключения,приложение_сервер  должно блокировать закрытие.
    Поэтому необходим подсчет подключений.

    Initialize -> inc(count);
    Код

    coInitialize;
    obj:=CreateComObject(CLASS_GUID) as Ixxx;
    ...


    destroy ->dec(count);
    Код

    obj:=nil;
    coUnInitialize;


    Со вторым, как раз  и проблема.
    Если поток, до закрытия приложения, не завершился, то destroy на сервере вызван не будет.
    Дождаться завершения потока в секции finalization (или в DllProc) невозможно - потоки к тому времени уже дохлые.
    Остается определить дополнительный метод COM objectа, который будет вызываться в finalization
    Код

    function Txxx._destroy: HResult;
    var all_ref:integer;
    begin
    repeat
    all_ref:=_Release; //Дабы убить объект
    until all_ref=0;
    // dec(count);
    end;
       

    Ну теперь отпадает вопрос  о
    Цитата
     Threading model
    .
    Остается только MULTITHREADED, поскольку COM object будет использоваться в разных потоках.
  • Еще один бок(только если заблокировано закрытие COM сервера)- если  COM object  создается/вызывается после того,как были закрыты/уничтоженны все предыдущие, то сразу за Initialize следует destroy. И мы имеем дырку от бублика вместо подключения к COM серверу.
    Это исправил добавлением строки _AddRef в  Initialize
  

Да здравствует "ВСЕ ЧЕРЕЗ ЖОПУ"!!!


 




Автор: cat512 31.5.2011, 09:24
чё - то у тебя как то сложно всё smile 

Автор: Чучмек 1.6.2011, 20:05
Цитата(cat512 @  31.5.2011,  09:24 Найти цитируемый пост)
чё - то у тебя как то сложно всё

А как проще?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)