Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2006.01.01;
Скачать: [xml.tar.bz2];

Вниз

как отработать события СОМ объекта принадлежащего классу 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.011 c
2-1134806230
melnik11
2005-12-17 10:57
2006.01.01
help!!!


2-1134687534
crazycorpse
2005-12-16 01:58
2006.01.01
Динамический массив n x m


4-1129968944
Энтри
2005-10-22 12:15
2006.01.01
Помогите вытащить переменную из структуры


11-1116359061
AK Delfin
2005-05-17 23:44
2006.01.01
Смена картинок в KOlToolBar


2-1134637775
Daria
2005-12-15 12:09
2006.01.01
и еще раз про EXCEL





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский