Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.01.01;
Скачать: CL | DM;

Вниз

как отработать события СОМ объекта принадлежащего классу TThread   Найти похожие ветки 

 
Rule ©   (2005-12-02 15:07) [0]

описываю ситуацию, в приложении создается отдельный поток, в этом потоке создается СОМ-сервер, который обладает событиями, для простоты эксперемента возьмем одно событие. Так вот когда происходит событие в сервере (сервер написаный мной) сервер выполняет вот такой вот код ...
try
   L := ClientList.LockList;
   for i:=L.Count-1 to L.Count-1 do
   begin
     T := TTerminal(L[i]);
     T.FLastCardNumber:=FLastCardNumber;
     T.FEmitent := FEmitent;
     T.FClientInfo := FClientInfo;
     T.FcardStart := FcardStart;
     T.FCardEnd := FCardEnd;
     T.FLimits := FLimits;
     T.FLimitCount := FLimitCount;
     T.FPurseCount := FPurseCount;
     T.FPurse := FPurse;
     if Assigned(T.Events) then T.Events.OnCardInsert;
   end;
 finally
   ClientList.UnlockList;
 end;

в списке клиентов хранятся ссылки на интерфейс клиентов ...
так вот смысл в чем, что когда происходит событие то до ходит до строки
     if Assigned(T.Events) then T.Events.OnCardInsert;
и пытается выполнить метод клиента и сервер подвисает, в это время на клиенте поток крутится в методе Execute  в цикле, пока его не завершит по флагу VCL  поток. И вот когда поток выходит из цикла Execute вот тогда и срабатывает событие ... тоесть событие сервера отработается только когда выйдет из  Execute.
Вопрос в том как это побороть ??? тоесть мож в цикле Execute можно узнать произошло ли событие или нет ? можно конечно сделать флаг объекта что при возникновении события он устанавливается ну а в цикле Execute проверять этот флаг, но это не выход, потомучто хотелось бы оставить всетаки нормальные события.

для полноты картины привожу полный код потока ...

unit uShlumbThread;

interface
procedure TShlumbThread.Execute;
var
 List:TList;
 QE:PShlumbQueryElement;
begin
 inherited;
 CoInitializeEx(nil,COINIT_APARTMENTTHREADED);
 StartTerminal;
 //FShlumb.StartPingCard;
 while not FTerminate do
 begin
     try
       List:=shlumbQueryList.LockList;
       if List.Count>0 then
         QE := List.First
       else
         QE := nil;
     finally
       shlumbQueryList.UnlockList;
     end;
    // FShlumb.StartPingCard;
     if QE<>nil then
     begin
       if QE.name="debetadv" then
       begin
         PayMoney(QE.summa);
       end;
       if QE.name="endping" then
       begin
         FShlumb.EndPingCard;
       end;
       if QE.name="startping" then
       begin
         FShlumb.StartPingCard;
       end;
       //отчищаем элемент
       try
         List:=ShlumbQueryList.LockList;
         List.Delete(List.IndexOf(QE));
         Dispose(QE);
         //P:=nil;
       finally
         ShlumbQueryList.UnlockList;
       end;
     end;
  end;

 if FShlumb.IsCardPinging then FShlumb.EndPingCard;
 FShlumb.Free;

 CoUninitialize;
end;

procedure TShlumbThread.StartTerminal;
var
 IFI:TIniFile;
 i:integer;
 ncomport:OleVariant;
 res:WaitResult;
begin
 FShlumb := TTerminal.Create(nil);
 FShlumb.AutoConnect:=True;
 FShlumb.OnCardInsert := Main.ShlumbCardInsertMain;
 FShlumb.OnCardRemove := Main.ShlumbCardRemoveMain;
 FTerminate := false;
 FLastPingCard := "";
 IFI := TIniFile.Create(ExtractFilePath(Application.ExeName)+"settings.ini");
 i := IFI.ReadInteger("SHLUMB","COMPORT",5);
 case i of
   1: ncomport := puCOM1;
   2: ncomport := puCOM2;
   3: ncomport := puCOM3;
   4: ncomport := puCOM4;
   5: ncomport := puCOM5;
   6: ncomport := puCOM6;
   7: ncomport := puCOM7;
   8: ncomport := puCOM8;
   9: ncomport := puCOM9;
 else ncomport := puCOM5;
 end;
 IFI.Free;
 FShlumb.InitUnit(bru9600,dbuSeven,pruEven,ncomport,sbuOneStopBit,res);
 if res<>WR_Ok then raise Exception.Create("Ошибка при открытии порта терминала Р+, дальнейшая работа программы невозможна !!!");
end;

помогите пожалйста, всем благодарен, кто обратил внимание ... надеюсь информация достаточная и полная ...


 
Rule ©   (2005-12-02 15:08) [1]

поправка это не полный код потока, а метод экзекьют и метод создания комобъекта, который вызывается вначале экзекьют


 
Rule ©   (2005-12-02 15:16) [2]

ещё одна поправка процедуры генерации сообщения на сервере:
try
  L := ClientList.LockList;
  for i:=0 to L.Count-1 do
  begin
    T := TTerminal(L[i]);
    T.FLastCardNumber:=FLastCardNumber;
    T.FEmitent := FEmitent;
    T.FClientInfo := FClientInfo;
    T.FcardStart := FcardStart;
    T.FCardEnd := FCardEnd;
    T.FLimits := FLimits;
    T.FLimitCount := FLimitCount;
    T.FPurseCount := FPurseCount;
    T.FPurse := FPurse;
    if Assigned(T.Events) then T.Events.OnCardInsert;
  end;
finally
  ClientList.UnlockList;
end;


 
Digitman ©   (2005-12-02 16:06) [3]

что говорят результаты пошаговой трассировки сабжа во встроенном отладчике ?


 
Rule ©   (2005-12-02 16:08) [4]

Digitman ©   (02.12.05 16:06) [3]
висит на сервере  if Assigned(T.Events) then T.Events.OnCardInsert;
до тех пор пока не закончится эезекьют на клиенте, как только н заканчивается, так сразу выполняется бработчик на клиенте ...


 
Rule ©   (2005-12-02 16:09) [5]

вот єтот обработчик на сервере вызывать через синхронайз метод ... ща буду пробовать


 
Набережных С. ©   (2005-12-02 17:14) [6]


> Rule ©

Сообщения кто из очереди выбирать будет, Пушкин? Дык он уже умер, как я недавно узнал:(


 
Rule ©   (2005-12-02 17:34) [7]

Набережных С. ©   (02.12.05 17:14) [6]
вот как раз это меня и интересует, как мне выбрать сообщения из очереди ???


 
Набережных С. ©   (2005-12-02 18:02) [8]


> Rule ©   (02.12.05 17:34) [7]


> в это время на клиенте поток крутится в методе Execute  
> в цикле, пока его не завершит по флагу VCL  поток. И вот
> когда поток выходит из цикла Execute вот тогда и срабатывает
> событие ...

В общем, довольно смутное описание, но, судя по всему, в этом самом цикле, в котором "крутится клиент", и надо бы выбирать и диспетчиризовать сообщения из очереди ентого клиентского потока. Тут, вишь ли, дело такое, СОМ для синхронизации меж потоками в STA использует сообщения, а выбрать их некому, получаецца. Вот если внутри клиентского вызова метода, то там дело другое, там за это COM отвечает, а вот снаружи ето дело клиента, ага.

А вообще-то, я тут второй литр балтики дососал, так что ты c моими советами поосторожней:)) Давай завтра что-ли, если не решишь. А пока бы поподробней расписал. Вот представь человека, который твоего кода в глаза не видел, где клиент, где сервер, какой сервер, какой код к кому - фиг знает... Вот для такого человека и расскажи:)


 
Rule ©   (2005-12-02 18:25) [9]

Набережных С. ©   (02.12.05 18:02) [8]
огромное спасибо, значит проблемму решил таким образом, в принципе то её обойти можно было, но это уже не та история, все решния пришли сразу :-)))

так вот решение такое, так как у меня МТА, когда я писал сервер я не знал зачем оно, только код усложняется, но решил поупрожнятся, но щас пригодилось :-) так вот просто в VCL потоке прописал   CoInitFlags:= COINIT_MULTITHREADED;
перед инициализацией приложения, таким образом у меня стал возможен доступ к СОМ серверам созданым в других потоках и обработчики событий я прицепил в методе Create моего потока.
Таким образом оплучилось что экзекьют себе пусть крутиться хоть до опупения, а вот обработчики будут выполняться в основном потоке, который с радостью отвечает всегда серверу :-)))

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

ссылка:
http://emanual.ru/download/210.html


 
Rule ©   (2005-12-02 18:28) [10]

оффтоп:
ЗЫ: всетаки тяжело с бодуна проги писать :-))) особенно многопоточные :-))), присоеденяюсь к Сергею и иду пить пива :-))).

большое спаибо всем кто откликнулся :-)))
сорри за оффтоп


 
Набережных С. ©   (2005-12-02 19:54) [11]


> Rule ©

Ну и замечательно:) Особо одобряю на счет пива:))) Тока не забывай, что в MTA нельзя строить предположений, в каком потоке СОМ будет выполнять тот или другой вызов, какой сочтет подходящим, тот и выберет. Значить, и синхронизацию надобно надежную обеспечить, не закладываться на основной.


 
Rule ©   (2005-12-02 20:18) [12]

Набережных С. ©   (02.12.05 19:54) [11]
спасибо за совет так и сделал, с двойной защитой, главное чтоб перекрестных блокировок теперь не возникло, завтра буду сервер на сей предмет изучать и проверять, спасибо большое за советы



Страницы: 1 вся ветка

Текущий архив: 2006.01.01;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.059 c
14-1133860176
Andrewmx
2005-12-06 12:09
2006.01.01
Работа с очередью


2-1134779323
shoni
2005-12-17 03:28
2006.01.01
Формы в Делфи


14-1134232474
x.pro
2005-12-10 19:34
2006.01.01
Доставка цветов.


2-1134821379
чайник9
2005-12-17 15:09
2006.01.01
Форма


8-1122279928
melena
2005-07-25 12:25
2006.01.01
частота пульсации