Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi String von Thread an Programm senden - Stilfrage! (https://www.delphipraxis.net/109004-string-von-thread-programm-senden-stilfrage.html)

TheMiller 22. Feb 2008 16:49


String von Thread an Programm senden - Stilfrage!
 
Hallo,

ich habe einen Thread, der einen String an die Hauptform senden soll. Da es sich nur um einen String handelt, möchte ich kein WM_COPYDATA verwenden. Nun habe ich eine Lösung gefunden, frage mich aber, ob diese "sauber" genug ist. Gerne nehme ich Verbesserungsvorschläge an!

Das Prinzip ist folgendes: Ich habe in der Hauptanwendung eine globale Stringvariable. Den Pointer übergebe ich an den Thread. Dieser erstellt einen String und greift direkt auf den Pointer zu und verändert die Variable. (Es ist sichergestellt, dass sich an dem Pointer und an der Inhalt der Variable in dieser Zeit nichts ändert). Danach kann ich normal auf diese Variable zugreifen. Ist das so in Ordnung?

Delphi-Quellcode:
var
  s_thread: String;

..
..

procedure TForm1.Button1Click(Sender: TObject);
var
  Th: TMyThread;
begin
  Th: TMyThread.Create(True);
  Th.s:=@s_thread;
  Th.resume;
end;

Delphi-Quellcode:
procedure TMyThread.Execute;
var
  str: String;
begin
  str:='Hallo, ich bin ein Test';
  s^:=str;
end;
Danke im Voraus

sirius 22. Feb 2008 18:15

Re: String von Thread an Programm senden - Stilfrage!
 
Nö, das geht so nicht.
Du musst schon das schreiben Synchronisieren und nicht nur den Zeiger auf den String kopieren.
Du kannst:

1. Anstatt WM_CopyData auch jede andere Message nehmen und synchronisiert (sendmessage) nen pointer auf die Adresse senden. Wobei das mit dem pointer nicht notwendig ist (Message alleine reicht), da in dem Moment auch der MainThread auf alle public Felder und Properties des TThreads zugreifen kann. Dein Thread wird ja aufgrund des sendmessage angehalten.

2. Du rufst mittels synchronize eine Methode des MainThreads auf und kannst von da auf die gesamte Klasse TThread zugreifen.

3. Eine Schöne Idee ist auch für solche "globalen" AustauschVariablen eine Klasse zu schaffen:
Delphi-Quellcode:
uses sysutils, classes;

type TContainer=class(TMultiReadExclusiveWriteSynchronizer) //oder =class(TSimpleRWSync)
       private
         FmyVariable:string;
         FOnChange:TNotifyEvent; //Vielleicht hier auch eine Liste
         function getmyVariable:string;
         procedure setmyVariable(value:string);
         function getOnChange:TNotifyEvent;
         procedure setOnChange(value:TNotifyEvent);
         procedure DoOnChange;
       public
         property myVariable:string read getmyVariable write setmyVariable;
         property OnChange:TNotifyEvent read getOnChange write setonchange;
     end;




implementation

function Tcontainer.getmyVariable:string;
begin
  beginread;
  result:=FmyVariable;
  endread;
end;
procedure TContainer.setmyVariable(value:string);
begin
  beginwrite;
  FmyVariable:=value;
  endwrite;
  DoOnChange;
end;
function Tcontainer.getOnChange:TNotifyEvent;
begin
  beginread;
  result:=FOnChange;
  endread;
end;
procedure Tcontainer.setOnChange(Value:TNotifyEvent);
begin
  beginwrite;
  FOnChange:=Value;
  endwrite;
end;
procedure Tcontainer.DoOnChange;
var tempOnChange:TNotifyEvent;
begin
  tempOnChange:=OnChange;
  if assigned(tempOnChange) then TempOnChange(self);
end;
Das Konzept habe ich selber noch nie angewandt, aber es wäre auch eine Möglichkeit. Mit Messages muss man ja auch mächtig aufpassen, dass man keine Threads gegenseitig locked. Das Problem hast du damit nicht. Intern wird hier mit Events gearbeitet.
Alternativ kannst du dieselbe Klasse auch von "TSimpleRWSync" ableiten. SimpleRWSync ist, wenn du paralleles Lesen von Threads eher selten hast. Dadurch wird die ganze Klasse etwas schneller. SimpleRWSync kapselt CriticalSections.

TheMiller 22. Feb 2008 18:20

Re: String von Thread an Programm senden - Stilfrage!
 
Ok... meine Lösung hatte zwar funktioniert, aber wenn du davon abrätst ist das ok.

Ich habe jetzt auch gesehen, dass ich direkt von der Anwendung einen String an den Thread schicken kann. Ich dachte das würde auch zu Fehlern wie bei der Stringübergabe zwischen DLL und EXE kommen. Doch das ist nicht so.

Also sende ich einen String vom MainThread an den eigentlichen Thread via globaler Variable und durch sendmessage wieder zurück. Das dürfte das ok sein, oder?

Da es sich nur um eine einzige Variable handelt, bin ich mit der jetzigen Lösung zufrieden. So können doch keine Fehler auftreten, oder?

sirius 22. Feb 2008 18:33

Re: String von Thread an Programm senden - Stilfrage!
 
Zitat:

Zitat von DJ-SPM
Ok... meine Lösung hatte zwar funktioniert, aber wenn du davon abrätst ist das ok.

Diese Fehler treten ja auch erst beim Kunden auf :zwinker: Das Problem besteht ja auch erst, wenn du zufällig zur gleichen Zeit aus mehreren Threads darauf zugreifst (und mindestens ein Thread schreibt )

Zitat:

Zitat von DJ-SPM
Ich habe jetzt auch gesehen, dass ich direkt von der Anwendung einen String an den Thread schicken kann. Ich dachte das würde auch zu Fehlern wie bei der Stringübergabe zwischen DLL und EXE kommen. Doch das ist nicht so.

Jep, ist ja auch derselbe Speichermanager.

Zitat:

Zitat von DJ-SPM
Also sende ich einen String vom MainThread an den eigentlichen Thread via globaler Variable und durch sendmessage wieder zurück. Das dürfte das ok sein, oder?

Aber achte darauf, dass du sendmessage nur in eine Richtung verwenden darfst. Also nur ein Thread darf an den anderen mittels sendmessage etwas schicken. Zurück geht es nicht. Aber du kannst, wie gesagt, in der Messagebearbeitungsroutine schreibend und lesend auf alle Felder der Klasse zugreifen.
Delphi-Quellcode:
procedure TThread.execute;
begin
...
  self.s:='Hallo';
  sendmessage(mainhandle,WM_threadsomething,0,0);
  //jetzt beinhaltet self.s einen neuen Wert
  ...
end;

procedure TForm1.getThreadMessage(var msg:TMessage); //message WM_threadsomething
begin
  //Da der Thread jetzt schläft, kannst du ohne Risiko auf alle Variablen des threads zugreifen
  showmessage(Thread.s);
  Thread.s:='gelesen';
end;
Zitat:

Zitat von DJ-SPM
Da es sich nur um eine einzige Variable handelt, bin ich mit der jetzigen Lösung zufrieden. So können doch keine Fehler auftreten, oder?

Ja, das ist auch mein Stil. (aber es gibt bestimmt einige hier, die dich dafür verhauen würden. :mrgreen:)

alzaimar 22. Feb 2008 18:36

Re: String von Thread an Programm senden - Stilfrage!
 
Eins der immer noch gültigen Grundprinzipien modularer Programmierung sind die Datenmodule. Hinter diesem Konzept verbergen sich Container, die Daten enthalten, die von den Modulen gemeinsam benutzt und verändert werden. Daher hat Delphi auch das TDatamodule-Konzept, obwohl das hier nur konzeptionell vergleichbar ist: Also jetzt nicht an TDatamodule denken.

Anders ausgedrückt sollt Du dich schnellstmöglich von der Methapher 'Senden von Daten' verabschieden. Die Daten sind irgendwo in einem Datenmodul und da sind sie auch gut aufgehoben. Die der Vorschlag von Sirius geht ja genau in diese Richtung.

Du hast also 'Container' (Datenmodule), die die Daten speichern und über geeignete Methoden sicherst Du konfliktfreien Zugang ztu den Daten.

Deine Threads verändern also asynchron diese Daten und teilen dann anderen Threads mit, das die Arbeit beendet ist, und die Weiterverarbeitung starten kann. Ob man das mit Messages oder Events löst, bleibt Dir überlassen.

Du könntest Dir auch vorstellen, das ein Thread immer einen Teil abarbeitet, dann einem 2.Thread mitteilt, das es etwas zu tun gibt. Der macht dann weiter, während sich Thread#1 wieder um den nächsten Happen kümmert usw. Dabei werden keine Daten verschickt, sondern nur Nachrichten.

Wenn Du an Anwendungsentwicklung im Team denkst, wird Code ja auch gemeinsam über ein CVS verwaltet und nicht immer komplett versendet...

TheMiller 22. Feb 2008 18:42

Re: String von Thread an Programm senden - Stilfrage!
 
Vielen Dank für eure Mühe, doch der letzte Beitrag hat mich nun wieder verunsichert? Ist die aktuelle Methode, dich ich oben beschrieben habe und auch nutze, jetzt verwendbar oder nicht. Das konnte ich jetzt nicht rauslesen. :oops:

Zitat:

Zitat von Ich
Also sende ich einen String vom MainThread an den eigentlichen Thread via globaler Variable und durch sendmessage wieder zurück. Das dürfte das ok sein, oder?


sirius 22. Feb 2008 19:31

Re: String von Thread an Programm senden - Stilfrage!
 
Verwendbar (mit genannten Einschränkungen) ist sie. aber du kannst eben auch OOP-konformer arbeiten. Dadurch gewöhnst du dir gleich die richtige Arbeitsweise an.
Du kannst zum Beispiel die Klasse TCotainer im Mainthread instanzieren und dann die Instanz an den Thread übergeben. Und hier kannst du problemlos auf die Propertys zugreifen und ich habe auch ein OnChange Ereignis eingebaut. diese beginwrite und endwrite (sowie *read) Abschnitte verhindern eben das gleichzeitige Schreiben mehrere Threads.

TheMiller 22. Feb 2008 19:52

Re: String von Thread an Programm senden - Stilfrage!
 
Hm...ich weis nicht ob ich das alles gerade richtig verstanden habe... Was würde bei meiner Lösung passieren, wenn ich mehrere Threads gleichzeit hätte (warum auch immer)?

alzaimar 22. Feb 2008 20:22

Re: String von Thread an Programm senden - Stilfrage!
 
Na durch die Kapselung der Zugrissmethoden machst Du deinen Container (altdeutsch 'Datenmodul') ja ggf. threadsicher. Das ist doch gerade das Gute an so einem Container bzw. der ganzen OOP-Chose. Wie Du genau den Zugriff auf die Daten implementierst (Datenbank, synchronisiert oder ob Du sie immer life vom Mond holst) ist gekapselt. Da man gar nicht mehr direkt an die Rohdaten herankommt, musst Du dir nie wieder Gedanken über Threadsicherheit machen (sofern Du den Zugriff eben synchronisierst).

Befolge doch einfach sirius' Rat, instantiiere den Container und übergebe dem Thread diese Instanz. Der Zugriff auf die konkreten Daten ist doch threadsicher.

TheMiller 22. Feb 2008 20:27

Re: String von Thread an Programm senden - Stilfrage!
 
Ok, jetzt habe ich glaub ich verstanden. Ich werde die Lösung einbauen. Komme aber erst wieder am Sonntag dazu.

Danke für eure Hilfe / Geduld!

TheMiller 22. Feb 2008 23:04

Re: String von Thread an Programm senden - Stilfrage!
 
Hallo,

hab jetzt doch noch eine Frage. Und zwar verstehe ich nicht, wie der Thread oder das Mainform mit der Klasse arbeitet. Ich habe die Klasse da stehen, aber wie verändere ich jetzt via Thread oder MainForm variablen? Und wo liegen diese Variablen?

Ist es so, dass diese Variablen IN der Klasse liegen und auch DORT verändert werden? Der Thread greift dann auf die Klasse zu und nimmt sich die Variablen? Wo wird die Klasse erstellt und instantiiert?

Hab das jetzt alles gesehen und im Kopf verarbeitet, aber die Klasse steht da immernoch (in mir drin) zusammenhanglos rum. Kann auch daran liegen, dass es schon ziemlich spät ist, aber ich versteh's nicht so ganz

Danke

wicht 23. Feb 2008 04:11

Re: String von Thread an Programm senden - Stilfrage!
 
Morgen,

ungefähr so müsste es sein:

Delphi-Quellcode:
type
  TForm1=class(TForm)
  private
    DataContainer: TContainer;

    DataContainerChange(Sender: TObject);
  end;

procedure TForm1.Create(Sender: TObject);
begin
  DataContainer := TContainer.Create;
  DataContainer.OnChange := DataContainerChange;
end;

procedure TForm1.DataContainerChange(Sender: TObject);
begin
  ShowMessage('Thread hat Daten verändert :-)');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Th: TMyThread;
begin
  Th: TMyThread.Create(True);
  // Th.s:=@s_thread;
  Th.DataContainer := DataContainer;
  Th.resume;
end;

Und im TThread.Execute kannst du dann eben mit
Delphi-Quellcode:
DataContainer.myVariable := 'threaddaten!';
Die Daten verändern, und der Hauptthread wird sogar über die Änderung informiert.

So habe ich es jedenfalls verstanden. Und der Code hier ist nur so geschrieben, bestimmt ein Fehler drin :mrgreen:

sirius 23. Feb 2008 08:08

Re: String von Thread an Programm senden - Stilfrage!
 
Zitat:

Zitat von wicht
So habe ich es jedenfalls verstanden.

So habe ich es auch gedacht :zwinker: (außer dass du vor der Deklaration von DataContainerChange noch "procedure" schreiben müsstest)

@DJ-SPM
Letztenendes ist dass nur in String in eine Klasse gakpaselt. Und die übergibst dann nur die Klasse und kannst den String von außen Threadsicher ändern.

TheMiller 23. Feb 2008 08:49

Re: String von Thread an Programm senden - Stilfrage!
 
Das Beispiel ist klasse! Ich habe es jetzt glaub ich verstanden.

Zu dumm, dass ich es morgen testen kann, da ich jetzt auf eine Hochzeit im anderen Ende Deutschlands fahre :twisted:

Naja, wird bestimmt auch lustig. Aber solche Prolematiken beschäftigen mich immer so lange, bis "ich" sie gelöst habe!

Danke jedenfalls!

SirThornberry 23. Feb 2008 09:52

Re: String von Thread an Programm senden - Stilfrage!
 
ich würde keine globale Variable nehmen sondern eine membervariable. Aber davon unabhängig reicht es wenn du den Zugriff auf den String mit einer CriticalSection absicherst.

sirius 23. Feb 2008 10:34

Re: String von Thread an Programm senden - Stilfrage!
 
Zitat:

Zitat von SirThornberry
Aber davon unabhängig reicht es wenn du den Zugriff auf den String mit einer CriticalSection absicherst.

Zitat:

Zitat von Sirius
SimpleRWSync kapselt CriticalSections.

:zwinker:

TheMiller 24. Feb 2008 13:40

Re: String von Thread an Programm senden - Stilfrage!
 
Bin wieder da!!!

Nochmal eine Frage zur "Container-Lösung"... Habe sie jetzt implementiert und die Container-Klasse als Extra-Unit mit in den Thread und in die Applikation eingebunden. Du hast aber die Methode "setMyVariable" als private deklariert. So kann ich ja nicht vom Thread oder von UnitX auf diese Methode zugreifen - oder mache ich was falsch?

Vielen Dank nochmals für den Code!

sirius 24. Feb 2008 13:53

Re: String von Thread an Programm senden - Stilfrage!
 
Dafür gibts ja das Property "myVariable". Dieses ruft im schreibenden Fall setmyVariable und im lesenden Fall getmyVariable auf.
Du solltest dir mal propertys anschauen, und wie die funktionieren :zwinker:

Du brauchst also nur myVariable zu nutzen. Schau dir mal an, was "wicht" geschrieben hat! (Da ist nur ein winziger Fehler drin)

TheMiller 24. Feb 2008 15:46

Re: String von Thread an Programm senden - Stilfrage!
 
Ja, ich habe es genauso gemacht, aber auf diese Art und weise "hängt" sich der Thread auf, wenn ich die Variable ändere.

Thread:

Delphi-Quellcode:
public
  DataContainer: TContainer;
end;

procedure Execute(...)
begin
  DataContainer.myVariable:='Hallo';
end;
Hauptprogramm

Delphi-Quellcode:
Th := TMyThread.create(true);
Th.DataContainer:=dataContainer;
Th.Resume;
Doch der Thread wird nicht bis zum Ende ausgeführt und die DataContainerChange wird auch nicht aufgerufen. Liegt das daran, dass die Anwendung, die den Thread aufruft, eine DLL mit DLL-Form ist und per Windows.SetParent in das Hauptprogramm eingebunden wird?

alzaimar 24. Feb 2008 15:50

Re: String von Thread an Programm senden - Stilfrage!
 
Hmm... Vielleicht liegts daran:

Im Thread=>SetMyVariable=>OnDataChange-Ereignis wird ausgelöst=>Im OnDataChange-Event wird die VCL benutzt => *aufhäng*

TheMiller 24. Feb 2008 15:59

Re: String von Thread an Programm senden - Stilfrage!
 
Kann ich das irgendwie synchronisieren?

Macci 24. Feb 2008 16:57

Re: String von Thread an Programm senden - Stilfrage!
 
Warum willst du es so umständlich machen? Mit Synchronize geht es doch ganz einfach. Also genau so, wie du es zu Anfang schon geschrieben hast, nur dass du statt

Delphi-Quellcode:
procedure TMyThread.Execute;
var
  str: String;
begin
  str:='Hallo, ich bin ein Test';
  s^:=str;
end;
einfach

Delphi-Quellcode:
procedure TMyThread.foo;
var
  str: String;
begin
  str:='Hallo, ich bin ein Test';
  s^:=str;
end;

procedure TMyThread.Execute;
begin
Synchronize(foo);
end;
schreibst.

TheMiller 24. Feb 2008 17:17

Re: String von Thread an Programm senden - Stilfrage!
 
Ok, das wäre auch eine Idee, aber in der anderen Lösung wird die Variable lesend oder/und schreibend geschützt, sodass nahezu alle Komplikationen ausgeschlossen sind.

Angenommen der User klickt schnell im Formular rum und löst 2 Threads aus, die Daten empfangen und schreiben beide auf die gleiche Variable, so wird mindestens eine Prozedur nicht richtig ausgeführt, da die Informationen schon durch den anderen Thread überschrieben worden sind.

So müsste das eigentlich sein, wenn ich das jetzt alles richtig verstanden habe.

Und da dieses Szenario durchaus leicht vorkommen kann, gehe ich lieber auf "Nummer sicher".

alzaimar 24. Feb 2008 18:18

Re: String von Thread an Programm senden - Stilfrage!
 
Synchronisiere erstmal den Zugriff auf die Container-Eigenschaft 'MyVariable'.

@Macci: Wenn Du weiterhin Anwendungen entwickeln willst, die sporadisch abk***en, dann nur weiter so. Wenn nicht, dann verwende solche Kontainerklassen. :zwinker:

TheMiller 24. Feb 2008 19:01

Re: String von Thread an Programm senden - Stilfrage!
 
Habe den Zugriff mittels weiterer Prozedur "ChangeVar" und dem Aufruf "Synchronzie(ChangeVar)" aus Execute synchronisiert - allerdings ohne Erfolg!

Macci 24. Feb 2008 19:05

Re: String von Thread an Programm senden - Stilfrage!
 
Zitat:

Zitat von DJ-SPM
Angenommen der User klickt schnell im Formular rum und löst 2 Threads aus, die Daten empfangen und schreiben beide auf die gleiche Variable, so wird mindestens eine Prozedur nicht richtig ausgeführt, da die Informationen schon durch den anderen Thread überschrieben worden sind.

So müsste das eigentlich sein, wenn ich das jetzt alles richtig verstanden habe.

Und da dieses Szenario durchaus leicht vorkommen kann, gehe ich lieber auf "Nummer sicher".

Nein, dieses Szenario kann niemals vorkommen, da der Nutzer nicht irgendwohin klicken kann, während eine synchronisierte Methode abläuft.

An alzaimar: Falsch, wenn man vermeiden will, dass Programme "sporadisch abkacken" (=nichtdeterministisches Verhalten wegen der Nebenläufigkeit von Threads entsteht) sollte man dafür Semaphore oder Mutex (=binäre Semapohore) verwenden. Genau das passiert im Grunde bei einer synchronisierten Methode. Deshalb verstehe ich nicht, wo du da ein Problem sieht.

TheMiller 24. Feb 2008 19:09

Re: String von Thread an Programm senden - Stilfrage!
 
Also, die Ursache des Problems - unabhängig von eurem "Prinzipstreit" (nicht böse gemeint :wink: ) - bei der vorgeschlagenen ContainerLösung scheint wirklich der Aufruf der DLL mit Windows.SetParent zu sein.

Ich habe ein neues Beispielprojekt erstellt, die Variablenänderung nochmals Synchronisiert und es funktioniert.

Aber was mach ich nun? Würde gerne die Einbindung des Moduls in den festen Bereich der Hauptanwendung behalten.

Macci 24. Feb 2008 19:14

Re: String von Thread an Programm senden - Stilfrage!
 
Hi DJ-SPM,

du kannst ja mal folgendes ausprobieren, probeweise:

Delphi-Quellcode:
procedure TTest.Execute;
begin
  { Thread-Code hier plazieren }
  Synchronize(foo);
end;

procedure TTest.Foo;
begin
while true do;
end;
Sobald du jetzt den Programmablauf des Threads TTest anstößt (z.B. mit TTest.Create(False); ) wird das ganze Programme festhängen - der Nutzer kann in dieser Zeit nirgendswo hinklicken. Brauchst dir also keine Sorgen machen, dass gleichzeitig mehrmals auf den String schreibend zugegriffen wird.

sirius 24. Feb 2008 19:15

Re: String von Thread an Programm senden - Stilfrage!
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ja, du musst natürlich in dem NotifyEvent aufpassen, dass du da immer noch im Thread bist.
Wenn du das Event, dass sich eine Variable geändert hat, lieber im MainThread ausführen willst, müsste man wahrscheinlich mit eine Message arbeiten. Oder auch einen Thread erstellen, der alle Threads verwaltet.

Ich habe mal im Anhang die mit einer asynchronen Message (asynchrone Messages sind risikofrei) veränderten TContainer-Klasse in einem Test-Programm.

Edit: Synchronize in einer DLL funktioniert nie.
Edit2: Und ich habe die Ableitung mal von TMultiReadWrite.... auf TSimpleRWSync geändert.

TheMiller 24. Feb 2008 19:18

Re: String von Thread an Programm senden - Stilfrage!
 
Zitat:

Synchronize in einer DLL funktioniert nie.
Das könnte echt einige fehlgeschlagene Versuche erklären :wall:

Mit Messages kann ich soweit umgehen (denke ich). Ich verwende sie zum Beispiel um die DLL wieder ordentlich zu entladen, wenn der Benutzer das Modul schließt.

Ich schaue mir das Beispiel gerade mal an. Ich danke euch nochmal für die Mühe, die ihr euch macht!

sirius 24. Feb 2008 19:20

Re: String von Thread an Programm senden - Stilfrage!
 
Zitat:

Zitat von DJ-SPM
Zitat:

Synchronize in einer DLL funktioniert nie.
Das könnte echt einige fehlgeschlagene Versuche erklären :wall:

Das ist ein Konzeptfehler der VCL.

Ob mein Konzept in einer DLL funktioniert kann ich jetzt auf Anhieb nicht sagen. Wenn du von SimpleRWSync ableitest (also einfach nur Critcal Sections verwendest), dann dürfte es kein Problem sein. Eher noch mit der zuerst geposteten Variante ohne Messages.

Macci 24. Feb 2008 19:29

Re: String von Thread an Programm senden - Stilfrage!
 
Wenn du mit einer DDL arbeitest, bastle dir doch einfach selbst ein Semaphor. Das geht recht einfach. Hab sowas in Delphi zwar noch nie gebraucht, aber letztens mal in Java, aber das Prinzip ist natürlich das gleiche.

TheMiller 24. Feb 2008 19:31

Re: String von Thread an Programm senden - Stilfrage!
 
Ähm.. was ist das? Die Lösung mit der Message gefällt mir. Aber erkläre mir das doch bitte mal!

Macci 24. Feb 2008 19:44

Re: String von Thread an Programm senden - Stilfrage!
 
Also ein Semaphore funktioniert vom Prinzip her wie ein Schüsselchen mit Murmeln drin ;-) Immer wenn ein Programmteil einen kritischen Abschnitt, also einen Abschnitt der nie beliebig oft gleichzeitg/nebenläufig ausgeführt werden darf, betreten will geschieht folgendes:
Der laufende Thread schaut nach, ob noch eine Murmel in der Schüssel drin ist, wenn ja, nimmt er sie raus und betritt den kritischen Bereich. Wenn nein, wartet er (entweder aktiv oder besser: passiv), bis wenigstens eine Murmel drin ist. Sobald er den kritischen Abschnitt verlassen hat, legt er diese Murmel zurück.
Hast du jetzt ein Schüsselchen mit genau einer Murmel drin, spricht von man von einem binären Semaphor oder auch Mutex.

Wenn du willst, kann ich dir mal zeigen, wie man sowas in Java machen würde. In Delphi übersetzen tu ich es aber nicht, geht aber einfach ;-)

TheMiller 24. Feb 2008 19:49

Re: String von Thread an Programm senden - Stilfrage!
 
Java bringt mir eigentlich jetzt nix. Aber eine Frage. Mache ich das nicht mit der Container-Unit und den BeginRead / BeginWrite bzw. End*? Ich sperre den Zugriff auf die Murmeln so, dass nur einer mit den Murmeln spielen darf. Hat er keinen Bock mehr zu spielen, geb ich den Bereich wieder frei - oder verstehe ich das jetzt falsch?

Macci 24. Feb 2008 19:52

Re: String von Thread an Programm senden - Stilfrage!
 
Ja, ist schon richtig so. Aber du musst halt aufpassen, dass der Vorgang des Murmel-Rausnehmens und Zurücklegens auf keinen Fall unterbrochen wird, denn dieser Vorgang selbst ist ja keine atomare Aktion und der Scheduler könnte dem Thread genau in dem Moment den Prozessor entziehen, wenn er gerade dabei war, die Murmel zurückzulegen, und dann käme es zu einem Deadlock.

TheMiller 24. Feb 2008 19:56

Re: String von Thread an Programm senden - Stilfrage!
 
Halte ich aber für eher unwahrscheinlich. Ist auch keine große Sache die im Thread passiert.

Nur eine Frage zum Beispiel aus dem angehängten Quellcode. Da wurde als Message eine solche verwendet:

Delphi-Quellcode:
const CM_OnChange=WM_User;
Hat das einen speziellen Grund, oder könnte ich auch

Delphi-Quellcode:
const
  WM_ThreadChange = WM_USER + 71
benutzen?

Diese Variante mit der Message funktioniert auf jeden Fall! Hab mir grad die Delphi-Hilfe zu Rate gezogen, um die Methoden nachvollziehen zu können

Macci 24. Feb 2008 20:05

Re: String von Thread an Programm senden - Stilfrage!
 
Also so ganz verstehe ich nicht. Warum willst du lieber die 2. Variante benutzen? Und warum sollte es nicht funktionieren? Probier es doch mal aus ;-)

TheMiller 24. Feb 2008 20:07

Re: String von Thread an Programm senden - Stilfrage!
 
Das war jetzt wieder so eine Stilfrage. Ich definiere eigene Messages immer so, wie ich es in der 2. Variante geschrieben habe. Hab's halt so gelernt. Deshalb hatte mich die 1.Variante auch etwas verwundert und ich dachte, dass das einen speziellen Grund hat.

Macci 24. Feb 2008 20:23

Re: String von Thread an Programm senden - Stilfrage!
 
Müsste genauso gehen, wenn du deine 2. Variante benutzt :-) Der Semaphore ist hier übrigens im "beginwrite" (murmel herausnehmen) und "endwrite" (murmel zurücklegen) versteckt :-) Würdest du keine DLL verwenden, ginge es ganz einfach mit Synchronize (funktioniert auch wie ein Semaphor).


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:28 Uhr.
Seite 1 von 2  1 2      

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