![]() |
AW: Mal wieder Threads
Wie versendest du denn Strings mit PostMessage?
|
AW: Mal wieder Threads
Sollte kein Problem sein, da ja alles im selben Prozess bleibt.
|
AW: Mal wieder Threads
Wenn es ein Pointer auf einen lokalen String ist, wird's potenziell ekelig.
|
AW: Mal wieder Threads
Nein. Ich mache mir für sowas immer Records. Das erste ist ein InUse:Boolean. Ist der Record belegt, nehm ich den nächsten oder warte bis einer frei wird.
Da wo ich "reinposte" sieht der anfang immer so aus
Delphi-Quellcode:
da habe ich dann die nummer auf dem record, der "zu mir" gehört. Der Record ist Global und da stehen dann alle sachen drinne die ich in dem moment brauche. Strings,Integer usw..
procedure TReadDataFrm.RefreshRDObj(var Msg: TMessage);
var i :Integer; begin i := Integer(Msg.lParam); Ich habe nun mal SendMessage genommen. Da der fehler nicht reproduzierbar ist, kann ich nur warten.... |
AW: Mal wieder Threads
Also, prinzipiell sollte man im Thread immer nur mit PostMessage arbeiten.
Mal so ganz ins blaue geraten: Du sendest den Text mit WM_COPYDATA - und das ist nicht Thread-geeignet. Ein bisserl mehr Quellcode wäre nett, dann könnte man vielleicht auch eine gescheite Aussage treffen und dir leichter weiterhelfen. Mit der Kristallkugel ist's am Wochenende nix, da ist die konsequent auf Urlaub... Gruß Luggi |
AW: Mal wieder Threads
Zitat:
Insofern ist PostMessage prinzipiell schon gut geeignet, aber eben nur, wenn es richtig gemacht wird. Wenn ich da aber schon etwas von globalen Records lese, schwant mir nichts Gutes. Wenn es ist wie ich vermute, wäre es kein Wunder, wenn SendMessage funktioniert... weil das schlicht wartet bis die Message abgearbeitet wurde und damit alles ggf. noch zur Verfügung steht. Aber genau das möchte man ja bei Threadkommunikation vermeiden. Aber wenn eben trotz mehrfacher Bitte (fast) kein Quelltext gepostet wird, kann auch niemand wirklich sinnvoll helfen... :roll: Es geht ja nicht um den gesamten Projektquelltext oder so, sondern nur um das Gerüst wie die Threads und deren Kommunikation denn nun aussehen. Deshalb: Zitat:
|
AW: Mal wieder Threads
Zitat:
Von dem neuen TCollectionItem übergibst du per PostMessage oder SendMessage die ID (nicht den Index!) und schickst das auf die Reise. Der Empfänger kann nun aus dieser Collection sich das passende Item (mit der ID) herausnehmen und hat auch alle Informationen. Generell würde ich auch die Jobs nicht als Thread definieren, sondern die Jobs durch einen WorkThread ausführen lassen. Der WorkThread wird über einen WorkManager gestartet und dieser verwaltet passenderweise auch noch die Collection mit den Nachrichten. Hier mal ein schnell hingetippeltes Projekt
Delphi-Quellcode:
Es gibt auch noch diese
type
IWorkManager = interface procedure SendMessage(<ParameterListe anpassen>); procedure PostMessage(<ParameterListe anpassen>); end; // Interface für den WorkJob IWorkJob = interface procedure SetWorkManager( aWorkManager : IWorkManager ); procedure DoExecute; end; TWorkThread = class( TThread ) private fWorkJob : IWorkJob; protected procedure Execute; override; public constructor Create( CreateSuspended : Booelan; aWorkJob : IWorkJob ); end; TWorkManager = class( TInterfacedObject, IWorkManager ) public procedure AddJob( aWorkJob : IWorkJob ); end; procedure TWorkManager.AddJob( aWorkJob : IWorkJob ); begin aWorkJob.SetWorkManager( Self ); with TWorkThread.Create( True, aWorkJob ) do begin FreeOnTerminate := True; Resume; end; end; ![]() Sowas baue ich aber lieber selber :) |
AW: Mal wieder Threads
Also ich kapsle einen String in einer Klasse. Das ist bestimmt oversized, aber bisher hatte ich damit keine Probleme...
(Das hier ist allerdings aus dem Gedächtnis)
Delphi-Quellcode:
Is das ok so?
Type
TStringContainer = Class Public MessageString : String; Constructor Create (aMessage : String); End; Constructor TStringContainer.Create (aMessage : String); Begin MessageString := aMessage End; ... Procedure TMyThread.SendAString (AString : String); Begin PostMessage(MainHandle, WM_STRING, Integer(TSTringContainer.Create(aString)),0); End; ... Procedure TMainTask.ReceivStringMessageHandler (Var Msg : TMessage); Begin DoSomethingWith(TStringContainer(Msg.wParam).MessageString); TStringContainer(Msg.wParam).Free End; Nachtrag: Da mir das mit der Referenzzählung bei Strings nicht geheuer ist, mache ich das so. @Sir Rufo: Threads mit FreeOnTerminate habe ich mir abgewöhnt, denn wenn ich die Anwendung beende und der Thread noch im Speicher rumfleucht, bekomme ich jedesmal eine schöne Exception, denn der Code zum Terminieren eines Threads baut darauf auf, das die Classes.pas noch nicht ihren finalize-Teil durchlaufen hat. |
AW: Mal wieder Threads
Da ich wirklich nicht alle posten kann, wäre einfach zu lang, habe ich mal die wichtigen sachen zusammen gestellt. Wenn ich was vergessen habe, dann beschimpft einfach :-D
Delphi-Quellcode:
Das hier ist dann im Thread der eigentliche aufruf. Er achtet noch auf InUse da es vorher ja mit Postmessage gemacht wurde.
type
TReadDataFrm = class(TForm) RzPanel1: TRzPanel; StatusBox: TRzGroupBox; [SNIP] private { Private-Deklarationen } procedure RefreshRDObj(var Msg: TMessage); message Refresh_RDObj; public { Public-Deklarationen } end; procedure TReadDataFrm.RefreshRDObj(var Msg: TMessage); var i :Integer; begin i := Integer(Msg.lParam); [SNIP] MyThread.InUse:=False; end; {RefreshRDObj(var Msg: TMessage)}
Delphi-Quellcode:
Apprun ist auch Global. Es wird alle 100ms auf 1 gesetzt, über einen normalen TTimer. Da grade dieses nicht mehrmals aufgerufen wird, ist das kein record-array.
if AppRun=1 then begin
AppRun:=0; if NOT MyThread.InUse then begin MyThread.i:=2; MyThread.InUse:=True; SendMessage(MyThread.WinHandle, Refresh_RDObj, 0, MyThread.i); end; end; Das teil sieht so aus.
Delphi-Quellcode:
Winhandle wird vor dem start des Thread gesetzt. Wie gesagt, das ist kein "eigener" Thread wie ich ihn im ersten post hier beschrieben habe, sondern ein TJvMTThread. Damit habe ich noch nie was gemacht. Alle meine progs liefen immer mit Thread wie im 1. post beschrieben. Vielleicht vergesse ich da was?!?
type
TMyThread = record InUse :Boolean; RunType :Integer; PathCount :Integer; FileCount :Integer; SizeCount :Int64; FileName :String; WinHandle :THandle; [SNIP] AktDirVar :String; AktProgress :Integer; i :Integer; Str :String; end; So, nun hab ich sooo lange gesucht und Copy&Pastet das ne Rote Box kam... [Nachtrag] Mit der Variante aus dem ersten post, habe ich ein prg gemacht was bis zu 200 threads zeitgleich laufen hat. Das klappt einwandfrei. Eventuell sollte ich vom TJvMTThread wieder weggehen und es so machen wie ich es gewohnt bin. |
AW: Mal wieder Threads
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:23 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz