AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi String von Thread an Programm senden - Stilfrage!
Thema durchsuchen
Ansicht
Themen-Optionen

String von Thread an Programm senden - Stilfrage!

Ein Thema von TheMiller · begonnen am 22. Feb 2008 · letzter Beitrag vom 25. Feb 2008
Antwort Antwort
Seite 1 von 5  1 23     Letzte »    
Benutzerbild von TheMiller
TheMiller

Registriert seit: 19. Mai 2003
Ort: Gründau
2.480 Beiträge
 
Delphi XE7 Architect
 
#1

String von Thread an Programm senden - Stilfrage!

  Alt 22. Feb 2008, 16:49
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
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#2

Re: String von Thread an Programm senden - Stilfrage!

  Alt 22. Feb 2008, 18:15
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.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von TheMiller
TheMiller

Registriert seit: 19. Mai 2003
Ort: Gründau
2.480 Beiträge
 
Delphi XE7 Architect
 
#3

Re: String von Thread an Programm senden - Stilfrage!

  Alt 22. Feb 2008, 18:20
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?
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#4

Re: String von Thread an Programm senden - Stilfrage!

  Alt 22. Feb 2008, 18:33
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 Das Problem besteht ja auch erst, wenn du zufällig zur gleichen Zeit aus mehreren Threads darauf zugreifst (und mindestens ein Thread schreibt )

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 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 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. )
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#5

Re: String von Thread an Programm senden - Stilfrage!

  Alt 22. Feb 2008, 18:36
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...
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Benutzerbild von TheMiller
TheMiller

Registriert seit: 19. Mai 2003
Ort: Gründau
2.480 Beiträge
 
Delphi XE7 Architect
 
#6

Re: String von Thread an Programm senden - Stilfrage!

  Alt 22. Feb 2008, 18:42
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.

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?
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#7

Re: String von Thread an Programm senden - Stilfrage!

  Alt 22. Feb 2008, 19:31
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.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von TheMiller
TheMiller

Registriert seit: 19. Mai 2003
Ort: Gründau
2.480 Beiträge
 
Delphi XE7 Architect
 
#8

Re: String von Thread an Programm senden - Stilfrage!

  Alt 22. Feb 2008, 19:52
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)?
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#9

Re: String von Thread an Programm senden - Stilfrage!

  Alt 22. Feb 2008, 20:22
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.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Benutzerbild von TheMiller
TheMiller

Registriert seit: 19. Mai 2003
Ort: Gründau
2.480 Beiträge
 
Delphi XE7 Architect
 
#10

Re: String von Thread an Programm senden - Stilfrage!

  Alt 22. Feb 2008, 20:27
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!
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 5  1 23     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:22 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz