AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Variablenübergabe Createthread verständnisproblem
Thema durchsuchen
Ansicht
Themen-Optionen

Variablenübergabe Createthread verständnisproblem

Ein Thema von TheGame1492 · begonnen am 19. Jan 2008 · letzter Beitrag vom 19. Jan 2008
Antwort Antwort
Benutzerbild von TheGame1492
TheGame1492

Registriert seit: 31. Jul 2004
Ort: Berlin
84 Beiträge
 
Delphi XE2 Professional
 
#1

Variablenübergabe Createthread verständnisproblem

  Alt 19. Jan 2008, 21:36
ahoi

Ich möchte einfach 5 Zahlen/Strings in eine Datei (test.txt) schreiben, wobei jede Zahl/String durch einen eigenen Thread in diese Datei geschrieben werden soll.

Hier mein Versuch:

Delphi-Quellcode:

procedure TForm1.Button1Click(Sender: TObject);

  function WriteStringInFile( p: pchar ):integer; stdcall;
  var
    f: textfile;
  begin
    AssignFile( f, 'test.txt' );
    Append(f);
    writeln( f, p );
    CloseFile(f);
  end;
var
  s: string;
  i: integer;
  TID: DWORD;
begin
  for i:=0 to 4 do
  begin
   s := IntToStr( i );
   TID := 123+i;
   CreateThread(nil, 0, @WriteStringInFile, pchar(s), 0, tid);
  end;
end;
Das Ergebnis in der Datei ist leider immer:

4
3
4
3
4


Wo liegt mein Fehler?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#2

Re: Variablenübergabe Createthread verständnisproblem

  Alt 19. Jan 2008, 22:06
1: Also erstmal ist dieser Dateizugriff nicht ThreadSave

Append öffnet eine Datei und setzt den Dateizeiger auf das Dateiende.
> wenn jetzt zwischen Append und WriteLn ein anderer Thread in die Datei was reingeschrieben hat, dann stimmt die Position nicht mehr, da sich das Dateiende verschiebt, aber der nicht Dateizeiger in f.

2: CreateThread übergibst du einen Zeiger auf den String "S"
gehtst dann weiter veränderst den String (für den nächsten Thread)
also könnte (und ist mit Sicherheit auch) sobald der Thread bei WriteLn ankommt der Zeiger ungültig.
> entweder ist in dem String ein anderer Inhalt (die nächste Zahl) oder noch schlimmer, der String steht inzwischen an einer anderen Speicheradresse und du greifst auf etwas zu, was kein String mehr sein muß.


Zitat von TheGame1492:
Ich möchte einfach 5 Zahlen/Strings in eine Datei (test.txt) schreiben, wobei jede Zahl/String durch einen eigenen Thread in diese Datei geschrieben werden soll.
warum?
bzw, was willst du mal erreichen...


Das Stringproblem kannst du aber leicht umgehn, indem du die Zahl übergibst und im Thread erst in einen String umwandelst.

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);

  function WriteStringInFile( i: integer ):integer; stdcall;
  var
    s: String;
    f: textfile;
  begin
    s := IntToStr(i);
    {hier Dateizugriff für andere Threads sperren}
    AssignFile( f, 'test.txt' );
    {kannst aber auch erst hier sperren ... Assign öffnet die Datei ja noch nicht}
    Append(f);
    writeln( f, s ); // oder einfach nur writeln( f, i );
    CloseFile(f); // das wandelt dann sleber intern um
    {und hier Dateizugriff wieder freigeben}
  end;

var
  i: integer;
  TID: DWORD;
begin
  for i:=0 to 4 do
  begin
    CreateThread(nil, 0, @WriteStringInFile, i, 0, @tid);
    // tdi ist ein Ruckgabeparameter ... heißt, da schreibt ChreateThread was rein
    // und du kannst das auslesen (es wird also nichts an ChreateThread übergeben)
  end;
end;
außerdem muß du den Zugriff auf die Datei noch irgendwie ThreadSicher machen ... z.B. über eine Delphi-Referenz durchsuchenTCriticalSection

und wenn/da du dich mit der WinAPI CreateThread nicht so auskennst (wenn ich mir TID anseh)
> schau dir mal Delphi-Referenz durchsuchenTThread an, das hat dann auch schon einige nette Dinge zur ThreadSynchronisierung eingebaut.




PS: außerdem setzt ChreateThread nicht IsMultithreaded auf True
und wenn IsMultithreaded auf False steht, dann ist der speicherManager ebenfalls nicht ThreadSave und es könnte noch weitere Probleme geben.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

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

Re: Variablenübergabe Createthread verständnisproblem

  Alt 19. Jan 2008, 22:12
Du übergibst einen Zeiger auf den String. Du kopierst ihn nicht bei der Übergabe. Und jetzt ist die Frage wer schneller ist. Der Thread mit dem Auslesen des Strings oder der MaintThread mit dem ändern. Und wenn der MainThread ändert, ist die Frage, wo kommt der neue String hin und wird der alte Platz überschrieben. Er könnte sogar ungültig werden, wodurch ein AV kommen müsste.

Andere Fehler, die noch kommen könnten:
1. Du öffnest die Datei zum schreiben. Falls ein anderer Thread die Datei noch offen hat, kommt es zum Fehler. Das ist halt Zufall und kann nicht vorhergesagt werden. Vielleicht kommt ein Threa mal beim schreiben ins stocken, weil die Festplatte grad anderweitig zu tun hat.
[/Roter Kasten]
2. Nimm statt CreateThread besser BeginThread. Dadurch sagst du dem Speichermanager wenigstens noch Bescheid, dass du Multithreaded arbeitest (Achtung: Dann nicht mehr stdcall).
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von TheGame1492
TheGame1492

Registriert seit: 31. Jul 2004
Ort: Berlin
84 Beiträge
 
Delphi XE2 Professional
 
#4

Re: Variablenübergabe Createthread verständnisproblem

  Alt 19. Jan 2008, 22:41
also ich will schon strings übergeben

die denn in die datei geschrieben werden sollen

und jeder String soll in einem eigenen Thread in die datei geschrieben werden

die Zahlen waren dabei nur als beispiel gedacht


und mit BeginThread schreibt der "kompletten wirrwarr"
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

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

Re: Variablenübergabe Createthread verständnisproblem

  Alt 19. Jan 2008, 22:44
Zitat von TheGame1492:
und mit BeginThread schreibt der nur kompletten wirrwarr
Zitat von sirius:
(Achtung: Dann nicht mehr stdcall).
Edit:
In deinem Fall würde ich dann doch zur Klasse TThread greifen. Da hast du dann gleich eine Klasse, in der du den String unterbringen kannst.
Delphi-Quellcode:
type TWriteFile=class(TThread)
       constructor create(s:string);
      protected
       procedure execute; override;
      private
       Fs:String;
end;
....


constructor TWritefile.create(s:string);
begin
  Fs:=s;
  Freeonterminate:=true;
  inherited create(false);
end;
procedure TWritefile.execute;
begin
  //Hier jetzt entweder mit CriticalSection oder mit synchronize in Datei schreiben
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ...
    TWriteFile.create(s);
  ...
end;
Andere Möglichkeit (ohne TThread) wäre, du assoziierst dir Speicher und übergibst den Pointer darauf und gibst den Speicher im Thread frei.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von TheGame1492
TheGame1492

Registriert seit: 31. Jul 2004
Ort: Berlin
84 Beiträge
 
Delphi XE2 Professional
 
#6

Re: Variablenübergabe Createthread verständnisproblem

  Alt 19. Jan 2008, 22:45
jo stdcall ist raus

Ergebnis/WirrWarr ist:


,

,
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

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

Re: Variablenübergabe Createthread verständnisproblem

  Alt 19. Jan 2008, 22:53
Edit oben

Das Wirrwarr entsteht durch die ganz oben genannten Gründe. Du hast vorhin nur Glück gehabt; und vielleicht auch, da Beginthread etwas länger dauert. Aber dein Thread wird ja hoffentlich nicht so kurz bleiben, sonst lohnt er sich ja nicht. Und damit wirst du zu ähnlichen Laufzeitproblemen kommen.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Antwort Antwort


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 04:19 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