Skocz do zawartości

[Delphi][Indy] Zawieszanie sie przy Create(self)


nektar

Polecane posty

Witam.

Mam problem przy tworzeniu nowej zakładki PageControl w kliencie irc która ma być tworzona przy próbie wejścia na nowy kanał. Ma ją wywoływać procedura OnJoin komponentu TidIRC ale za każdym razem kończy się to zawieszeniem się programu. Przed zawieszeniem się zostają wykonane jeszcze kolejne polecenia takie jak wypisanie tekstu na nowoutworzonym memo.

Próbowałem już filtrować komunikaty serwera i reagować na IdIRC1Raw ale sytuacja się powtarza.

Nie pojawiają się żadne błędy ani komunikaty. Komplikacja też przechodzi bez problemu.

Co dziwne wywołanie funkcji tworzenia nowej zakładki przez przycisk działa bez zarzutu i nie powoduje zawieszenia się.

 

Fragment programu:

 

Wywołanie funkcji:

procedure TForm1.IdIRC1Join(ASender: TIdContext; const ANickname, AHost,
 AChannel: string);
begin
 if ANickname = idirc1.nickname then
   begin
 CreateChannelTab(AChannel);
 GetMsg(AChannel,' *** Witaj na kanale ' + AChannel + ' ***');
   end;
end;
[ui'
function Tform1.CreateChannelTab(NewTabName : String) : Boolean;
var
   NewTab: TTabSheet;
   NewListBox: TListBox;
   Newedit: TEdit;
   NewMsgWindow: TMemo;
begin
channels[chaninxtmp] :=  NewTabName;

NewTab := TTabSheet.Create(self);
try
with NewTab do
 begin
   Caption := NewTabName;
   PageControl := PageControl1;
 end;
except
 on E: Exception do ShowMessage(E.Message+' '+IntToStr(E.HelpContext));
 end;

NewListBox := TListBox.Create(self);
try
   with NewListBox do
    begin
     Left := 616;
     Top := 0;
     Width := 121;
     Height := 428;
     TabOrder := 0;
     Parent := NewTab;
     Name := 'ListBox' + inttostr(chaninxtmp);
    end;
except
 on E: Exception do ShowMessage(E.Message+' '+IntToStr(E.HelpContext));
end;


NewMsgWindow := Tmemo.Create(self);
try
 with NewMsgWindow do
   begin
     ReadOnly := true;
     Left := 0;
     Top := 0;
     Width := 617;
     Height := 428;
     Align := alCustom;
     Parent := NewTab;
     ReadOnly := True;
     OnClick := FormActivate;
     OnMouseUp := MsgWindowMouseUp;
     Name := 'MsgWindow' + inttostr(chaninxtmp);
     clear;
   end;
except
 on E: Exception do ShowMessage(E.Message+' '+IntToStr(E.HelpContext));
end;

Newedit := TEdit.Create(self);
try
with NewEdit do
begin
   Left := 0;
   Top := 405;
   Width := 732;
   Height := 20;
   Align := alBottom;
   TabOrder := 1;
   OnKeyPress := ServerEditKeyPress;
   Parent := NewTab;
   Name := 'chanedit' + inttostr(chaninxtmp);
   OnKeyPress := EditEnter;
   clear;
end;
except
 on E: Exception do ShowMessage(E.Message+' '+IntToStr(E.HelpContext));
end;

inc(chaninxtmp);
Result := true;

end; 

 

Z góry dziękuję za pomoc

 

P.S. Delphi 2007(RAD Studio) + Indy 10.1.5

Link do komentarza
Udostępnij na innych stronach

Nie wiem czy ten komponent dziala na watkach, ale zakladam ze tak. Jesli tak to wszystkie odwolania do VCL musza byc zsynchronizowane.

zrob w OnJoin (czy w jakiesj to sie wiesza) wywolanie takie Synchronized(myProc). A w myProc zrob wlasciwa obsluge zdarzenia. Od tego bym zaczal.

Always Dark<br />u1_tt_logo.png banner-1.pngexFabula-banner.pngson_banner_ubersmall.jpg

Link do komentarza
Udostępnij na innych stronach

Nie wiem czy ten komponent dziala na watkach, ale zakladam ze tak. Jesli tak to wszystkie odwolania do VCL musza byc zsynchronizowane.

zrob w OnJoin (czy w jakiesj to sie wiesza) wywolanie takie Synchronized(myProc). A w myProc zrob wlasciwa obsluge zdarzenia. Od tego bym zaczal.

 

próbowałem synchronizować przez synchronize; ale nie mam możliwośći podania tej funkcji parametru. Gdy zrobiłem synchronize(TmpProcCreate); kompilator pluje 'E2066 Missing operator or semicolon'.

 

Zauważyłem też, że program wiesza się dopiero w momencie gdy nowa zakładka staje sie aktywna. Mogę pisać w innych zakładkach bez problemu aż kliknę na tą nową.

Link do komentarza
Udostępnij na innych stronach

przez synchronize mozesz przekazac funkcje bez parametrow czyli robisz takie obejscie:

1) ustawiasz w swoim obiekcie parametry ktore ma uzyc metoda zsynchronizowana (najlepiej obuduj to sekcja krytyczna)

2) wywolujesz metode przez Synchronize, ta metoda siegnie do ustawionych w punkcie 1 parametrow.

 

Co do bledu znaczy ze zapomniales dodac srednika lub przecinka :) Bez kodu nie mam pojecia o co chodzi

 

Co do zawieszania, ustaw breakpointa tuz przed zawieszeniem sie. Skapiluj program z ustawieniem na zakladce kompilatora (use debug dcu) i zacznij uzywac F8.

Always Dark<br />u1_tt_logo.png banner-1.pngexFabula-banner.pngson_banner_ubersmall.jpg

Link do komentarza
Udostępnij na innych stronach

przez synchronize mozesz przekazac funkcje bez parametrow czyli robisz takie obejscie:

1) ustawiasz w swoim obiekcie parametry ktore ma uzyc metoda zsynchronizowana (najlepiej obuduj to sekcja krytyczna)

"Wydaje" mi się, że prawidłowo obudowałem funkcje:

 

 function Tform1.CreateChannelTab(NewTabName : String) : Boolean;
var
   NewTab: TTabSheet;
   NewListBox: TListBox;
   Newedit: TEdit;
   NewMsgWindow: TMemo;
   CriticalSection: TRTLCriticalSection;
begin
 InitializeCriticalSection(CriticalSection);
 EnterCriticalSection(CriticalSection);

 channels[chaninxtmp] :=  NewTabName;

NewTab := TTabSheet.Create(self);
try
with NewTab do
 begin
   Caption := NewTabName;
   PageControl := PageControl1;
 end;
except
 on E: Exception do ShowMessage(E.Message+' '+IntToStr(E.HelpContext));
 end;

......ciach......

Newedit := TEdit.Create(self);
try
with NewEdit do
begin
   Left := 0;
   Top := 405;
   Width := 732;
   Height := 20;
   Align := alBottom;
   TabOrder := 1;
   Parent := NewTab;
   Name := 'chanedit' + inttostr(chaninxtmp);
   OnKeyPress := EditEnter;
   clear;
end;
except
 on E: Exception do ShowMessage(E.Message+' '+IntToStr(E.HelpContext));
end;

LeaveCriticalSection(CriticalSection);
inc(chaninxtmp);
Result := true;

end;

 

przy procedure TIdThread.Execute; w IdTread.pas

 

Nie wiem jak dokładniej to opisać, mam nadzieje, że jest zrozumiałe. Na życzenie mogę dołączyć źródło programu.

Link do komentarza
Udostępnij na innych stronach

1) wywoluje sie Synchronize(twojaProcedura), przy czym synchronize moze byc wywolane TYLKO z zakresu watku. Wywolanie synchronize na glownym watku moze prowadzic do deadlocka (o czym pisze w helpie)

 

czyli twoja procka powinna wygladac tak

 

procedure TForm1.IdIRC1Join(ASender: TIdContext; const ANickname, AHost,
AChannel: string);
 begin
   fChanel := AChanel;
   synchronize( createchanneltab );
end;
vhćyZwŚ,ł<ćz7zZhr7Ź)0^dŁ-hśh)Ąźui'
procedure TForm1.IdIRC1Join(ASender: TIdContext; const ANickname, AHost,
AChannel: string);
 begin
   critSection.enter;
   fChanel := AChanel;
   synchronize( createchanneltab );
   critSection.leave;
end;

gdzie critSection jest typu TCriticalSection (wiecej w helpie i googlu).

 

To co pisze tyczy sie pracy wielowatkowej. Objaw ktory piszesz swiadczy o tym ze masz cos zrabane w obsludze tego taktu, nie wiem czy sam go tworzysz czy tworzy go cos innego.

 

Przeanalizuj jak pokolei ida eventy i czy masz to wywolanie z watku pobocznego czy z glownego watku programu.

Niewiele wiecej moge ci pomoc.

Always Dark<br />u1_tt_logo.png banner-1.pngexFabula-banner.pngson_banner_ubersmall.jpg

Link do komentarza
Udostępnij na innych stronach

.....ciach....
   synchronize( createchanneltab );
.... ciach...
Ćzh7
%jxł)'7jśŚz+\"y^uzIZ#jŁŚyZui'procedure Synchronize(Method: TThreadMethod); overload;

znajduje się w IdTread.pas i pochodzi z samego Indy. Wywołuję ją sam komponent TidIrc a nie ja.

 

Próbowałem znów bezskutecznie zastosować Twoje porady. Nic nie pomaga. Mam tez wrażenie, że ten problem moze występować tylko u mnie. Może coś pogrzebalem przy aktualizacji pakietu indy. Dlatego jeżeli ktoś mógłby skompilować program u siebie i sprawdzić czy zachowuje się tak samo byłbym wdzięczny.

 

Żródło programu

Link do komentarza
Udostępnij na innych stronach

Zarchiwizowany

Ten temat jest archiwizowany i nie można dodawać nowych odpowiedzi.

×
×
  • Utwórz nowe...