| Autor |
Beitrag |
rochus
      
Beiträge: 416
Win XP Prof, Fedora Core 4, SuSE 7.0
D7 Ent, D2005 Pers
|
Verfasst: So 17.08.03 20:29
Hallo,
mein Problem könnte man auch ins Netzwerke schieben, hat aber - denke ich - mehr mit dem hier zu tun.. ich fang dann mal an:
ich hab nen server und nen client, der client kann support anfragen schicken, durch die dann ein bestimmtes fenster (abgeleitet von TfrmSupport) erstellt werden soll. nun ist ja natürlich klar, dass dieses Fenster dynamisch erstellt werden soll. dies geschieht (da ich die INdy komponenten verwende) aus der procedure OnExecute des IDTCPServers heraus. Mal ein kleiner code-ausschnitt:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure TCPServerexecute(..) var strClient, strTemp: string; strSupport: TStringList; begin strTemp := AThread.connection.readln; if strTemp = '&support' then begin strSupport := TStringList.create; strClient := Athread.connection.readln; AThread.connection.readstring(strSupport); Application.CreateForm(TfrmSupport,frmSupport); frmSupport.show; frmSupport.FillWithData(strClient,strSupport); strSupport.Free; end; end; |
das ist ein ausschnitt der onexecute, die fillwidthdata funktion tut nichts anderes als ein label.caption mit strClient füllen und ein memo mit strSupport.
sobal dieses frmSupport.show aufgerufen wird, hängt mein programm! die form wird nichtmal ganz gezeichnet, nur di flächen (also grau für normal, weiß für memo und edit-felder..)
woran liegt das?
gruß
rochus
|
|
worm
      
Beiträge: 135
D6 Prof
|
Verfasst: So 17.08.03 23:35
Wahrscheinlich nicht an dem von Dir geposteten Code. Erstmal würde ich vorschlagen, frmSupport.FillWithData vor frmSupport.Show aufzurufen, und dann solltest Du mal gucken, ob in frmSupport.FillWithData oder frmSupport.OnShow irgendwo eine Endlosschleife läuft. Das würde nämlich das Fenster davon abhalten, die Botschaften von Windows zu empfangen und sich zu zeichnen  .
Cya, f0k
_________________ In the beginning, the universe was created. This has made a lot of people very angry, and is generally considered to have been a bad move.
|
|
rochus 
      
Beiträge: 416
Win XP Prof, Fedora Core 4, SuSE 7.0
D7 Ent, D2005 Pers
|
Verfasst: So 17.08.03 23:57
naja, in der newsgroup hab ich gehört, dass das daran liegt, dass indy in nem gesonderten thread abläuft und in dem vcl nix zu suchen hat..
deine methode hatte ich zuvor so:
frmsupport.showwithdata(...)
wobei ich dort die daten übergeben hab und dann in der showwithdata nach dem zuweisen der daten show; ausgeführt hab. selber effekt.. in der onshow der frmsupport ist nichts, also keine deklaration für onshow..
|
|
worm
      
Beiträge: 135
D6 Prof
|
Verfasst: Mo 18.08.03 00:46
Hmm, sehr merkwürdig... im Moment fällt mir nichts andres ein als: Poste mal deine FillWidthData-Prozedur. Allerdings: Wäre da eine Endlosschleife drin, wäre das Fenster bei deiner ersten Variante nie angezeigt worden. Also muss der Fehler eigentlich woanders liegen.
Was passiert, wenn Du das Fenster nach dem FillWidthData nicht mit Show, sondern mit ShowModal anzeigst?
_________________ In the beginning, the universe was created. This has made a lot of people very angry, and is generally considered to have been a bad move.
|
|
rochus 
      
Beiträge: 416
Win XP Prof, Fedora Core 4, SuSE 7.0
D7 Ent, D2005 Pers
|
Verfasst: Mo 18.08.03 10:47
hmm, mit showmodal funktioniert es ohne weiteres!!!!
hier aber mal die procedure, die ich nun verwende zum datenfüllen und anzeigen (ist ganz wenig!)
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| procedure TfrmSupport.ShowWithData(strClient: string; strText: TStringList); begin FClient := AnsiUpperCase(strClient); lblClient.Caption := FCLient; edtQuestion.Lines := strText; ShowModal; end; |
|
|
worm
      
Beiträge: 135
D6 Prof
|
Verfasst: Mo 18.08.03 23:58
Ah, ich glaube hier liegt der Fehler: Durch "edtQuestion.Lines := strText;" kopierst Du die Daten nicht, sondern edtQuestion.Lines zeigt dann auf die selbe Instanz der TStringList wie strText. Diese Stringlist gibst du aber im aufrufenden Thread direkt nach ShowWithData wieder frei. Folge ist, dass FrmSupport.edtQuestion.Lines auf ein ungültiges (da freigegebenes) Objekt zeigt.
Mit ShowModal ging es, weil dann der aufrufende Thread warten muss, bis Du das Fenster wieder geschlossen hast. Dadurch kann er die StringList auch erst danach wieder freigeben.
Lange Rede, kurzer Sinn: Versuch's mal mit "edtQuestion.Lines.Assign(strText);" und dem normalen Show, das müsste eigentlich dann gehen. Wenn ich mich jetzt nicht irgendwo verplant hab.
Cya, worm
_________________ In the beginning, the universe was created. This has made a lot of people very angry, and is generally considered to have been a bad move.
|
|
rochus 
      
Beiträge: 416
Win XP Prof, Fedora Core 4, SuSE 7.0
D7 Ent, D2005 Pers
|
Verfasst: Di 19.08.03 01:21
hi,
schön, wenn es das wäre :/ ich hab es so gemacht, wie du meintest.. warte, ich häng mal meine onexecute hier rein:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68:
| procedure TfrmCManServer.IDTCPSCManServerExecute(AThread: TIdPeerThread); var strTemp : string; strClient: string; strLog : string; strLogType : string; strSupport: TStringList; intSupport : integer; strMsg : string; i : integer; filestream : TFileStream; filesize : int64; strExeDir, strFullDir : string; begin strTemp := AThread.Connection.ReadLn();
strTemp := AnsiUpperCase(strtemp); if strTemp = AnsiUpperCase('&@connect') then begin end;
if strTemp = AnsiUpperCase('&@log') then begin end;
if strTemp = AnsiUpperCase('&@clientfile') then begin end;
if strTemp = AnsiUpperCase('&@support') then begin strSupport := TStringList.Create; strClient := AThread.Connection.ReadLn(); intSupport := Athread.connection.ReadInteger;
for i:=0 to intSupport-1 do strSupport.Add(AThread.Connection.ReadLn); Application.CreateForm(TfrmSupport,frmSupport); frmSupport.ShowWithData(strClient,strSupport); end;
if strTemp = AnsiUpperCase('&@msg') then begin strClient := AThread.connection.readlN; strMsg := Athread.connection.readln; ShowMessage(strClient + ': ' + strMsg); end;
end; |
achja, was mir noch aufgefallen ist: wenn ich den client dann disconnecte, dann gibt sich das programm wieder frei! mithilfe von dem, was du mir gesagt hast, wird zumindest die form korrekt aufgebaut und dann bleibt sie stehen... :/ ich probiers mal eben über nen extra thread für das fenster.
|
|
Aya
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: Di 19.08.03 01:49
Hi,
wie du schon richtig gesagt hast läuft Indy Thread basiert ab, und da mußt du deinen Thread erst mit dem MainThread deines Programmes Synchronisieren.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| procedure OpenForm; begin strSupport := TStringList.create; strClient := Athread.connection.readln; AThread.connection.readstring(strSupport); Application.CreateForm(TfrmSupport,frmSupport); frmSupport.show; frmSupport.FillWithData(strClient,strSupport); strSupport.Free; end;
procedure TCPServerexecute(..) var strClient, strTemp: string; strSupport: TStringList; begin strTemp := AThread.connection.readln; if strTemp = '&support' then begin Synchronize(OpenForm); end; end; |
So sollte das ganze klappen, is allerdings ungetestet.. ansonsten schau dir mal in der Hilfe an was da zu Synchronize steht.
Au'revoir,
Aya~
_________________ Aya
I aim for my endless dreams and I know they will come true!
|
|
rochus 
      
Beiträge: 416
Win XP Prof, Fedora Core 4, SuSE 7.0
D7 Ent, D2005 Pers
|
Verfasst: Di 19.08.03 14:25
Danke für eure Bemühungen
also, ich hab das jetzt wie folgt:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66:
| SupportStrings: TStringList; SupportClient : String; aSupportCS : TCriticalSection;
form.create; begin SupportStrings := TStringList.create; aSupportCs := TCriticalSection.Create; end;
formdestroy; begin aSupportCS.Destry; end;
ServerExecute; begin if strTemp = AnsiUpperCase('&@support') then begin strSupport := TStringList.Create; strClient := AThread.Connection.ReadLn(); intSupport := Athread.connection.ReadInteger;
for i:=0 to intSupport-1 do strSupport.Add(AThread.Connection.ReadLn); aSupportcs.Enter; try SupportStrings.Clear; SupportClient := strClient; SupportStrings := strSupport; finally aSupportCs.Leave; end;
Athread.Synchronize(SupportForm); end; end;
SupportForm; var myList : TStringList; myClient: string; begin myList := TStringList.Create;
aSupportCS.Enter; try myClient := SupportClient; myList := SupportStrings; SupportStrings.clear; SupportClient := ''; finally aSupportCS.Leave; end; Application.CreateForm(TfrmSupport,frmSupport); frmSupport.ShowWithData(myClient,myList); myList.Free; end; |
aber irgendwie scheint es nicht zu wollen. zumindest bekomme ich zwar die frmSupport angezeigt, doch der inhalt fehlt.. leider. und wenn der client disconnected und dann wieder connected und schließlich ne anfrage sendet wird er gracefull disconnected und wenn ich versuche, den server zu schließen, kommt ne fehlermeldung..
woran kann das noch liegen?? gruß
rochus
|
|
rochus 
      
Beiträge: 416
Win XP Prof, Fedora Core 4, SuSE 7.0
D7 Ent, D2005 Pers
|
Verfasst: Di 19.08.03 17:57
hallöchen. ich denke, ich bin zu einer lösung gekommen  endlich.. wenn die MODs das wollen, können sie es auch irgendwie in die FAQ einbauen unter -> "aus einem Indy-Thread heraus dynamisch eine Form erstellen und dynamisch mit Daten füllen".
also, das sieht nun folgendermaßen aus:
es wird eine Unit erstellt, in der der Typ TfrmSupport deklariert wird. die muss natürlich in der Hauptunit eingebunden werden..
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54:
| TForm1 = class(TForm) public procedure CreateNewSupportWin(Sender: TObject); end;
TSupportThread = class(TThread) private FClient : string; FText : string; public constructor Create(AClient, AText: string); procedure Execute; override; end;
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread); var strTemp : string; strClient: string; strLog : string; begin strtemp := AThread.Connection.ReadLn(); if strTemp = '&@support' then begin with TSupportThread.Create('abc','def') do FreeonTerminate := true; end; end;
constructor TSupportThread.Create(AClient, AText: string); begin inherited Create(False); FClient := AClient; FText := AText; end;
procedure TSupportThread.Execute; begin OnTerminate := form1.CreateNewSupportWin; end;
procedure TForm1.CreateNewSupportWin(Sender: TObject); begin Application.CreateForm(TfrmSupport,frmSupport); with TSupportThread(Sender) do begin frmSupport.memo1.lines.add(FText); frmSupport.label1.Caption := FClient; end; frmSupport.Show; end; |
so, das ganze wird jetzt noch ausgiebig getestet..
falls jemand einen denkfehler darin entdeckt, der melde sich bitte
gruß
rochus
|
|
|