Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Multithreading (Access Violation) (https://www.delphipraxis.net/190911-multithreading-access-violation.html)

taveuni 21. Nov 2016 10:18

AW: Multithreading (Access Violation)
 
Du erstellst im Execute X-Connections und Querys mit der gleichen Variable.

Delphi-Quellcode:
  while not Terminated do
  begin
und gibst sie beim ersten erfolgreichen wieder frei. Die anderen gucken dann in die Röhre

exchange 21. Nov 2016 11:05

AW: Multithreading (Access Violation)
 
Hallo,
meiner Meinung nach ist das egal, da ich alles wieder freigebe was ich vorher generiert habe.

Aber gut. Zum Testen while Schleife entfernt, sodass jeder Thread einmalig durchläuft.

Fehler bleibt.

p80286 21. Nov 2016 11:29

AW: Multithreading (Access Violation)
 
Auf den ersten Blick erscheint mir der Code des zweiten Beispiels ganz in Ordnung, nur der Sinn des
Delphi-Quellcode:
while not terminated
erschließt sich mir nicht ganz.

Wie wäre es wenn Du den Code mit ein paar exeptions aufhübschen würdest um den Fehler etwas einzugrenzen?

Gruß
K-H

stahli 21. Nov 2016 11:36

AW: Multithreading (Access Violation)
 
Zitat:

Zitat von exchange (Beitrag 1354254)
Darf man einen Thread nicht nacheinander ausführen? Einzelnd funktionieren die Threads auch.

Stell Dir vor, Du hast einen Thread, der 5 mal I := I + 1 ausführt und einen zweiten, der 5 mal I := I - 1 ausführt. Beide Threads brauchen ca. 1/2 Sekunde dafür.

Wenn Du Thread 1 startest , eine Sekunde wartest und Thread 2 ausführst, ist I wie vor den Threads 0.

Wenn Du beide Threads unmittelbar nacheinander ausführst, sollte eigentlich ja auch 0 rauskommen. Tut es aber nicht zwangsläufig.

"I := I + 1;" wird in mehreren CPU-Zyklen ausgeführt:

Merke Wert von I
Merke 1
Addiere beide Zahlen
Schreibe Ergebnis in I

Analog wird für Thread 2 folgendes getan:

Merke Wert von I
Merke 1
Subtrahiere Zahl2 von Zahl1
Schreibe Ergebnis in I

Wenn beide Threads gleichzeitig laufen bestimmt Windows, wann welcher Thread Arbeitszeit bekommen soll. Dazu wird z.B. Thread1 unterbrochen und Thread2 bekommt Arbeitszeit.

Dann passiert u.U. folgendes:

(Thread1)
Merke Wert von I
Merke 1
Addiere beide Zahlen
-->(Thread2)
Merke Wert von I
Merke 1
Subtrahiere Zahl2 von Zahl1
Schreibe Ergebnis in I
<--(weiter in Thread1)
Schreibe Ergebnis in I

Die Arbeit von Thread2 wird somit im Ergebnis nicht berücksichtigt.
Als Ergebnis kann alles zwischen -5 bis +5 raus kommen.


Wenn nicht nur einfache Integervariablen geteilt werden kann es zu weitaus schwerwiegenderen Fehlern bis hin zu kompletten Abstürzen kommen.

Man muss also darauf achten, dass gemeinsame Ressourcen gegen kritische gemeinsame Zugriffe abgesichert werden.


[EDIT] Das nur als grundsätzliche Anmerkung. Ob im genannten Beispiel so ein Problem vorliegen kann, kann ich nicht beurteilen.

Der schöne Günther 21. Nov 2016 11:42

AW: Multithreading (Access Violation)
 
Ich habe das Thema nur überflogen da ich zu UniDac nichts sagen kann.

Aber:
- Beide Threads haben doch überhaupt keine (offensichtlich) gemeinsam verwendeten Resourcen, alles ok
- Das "Thread.Create(False)", "While not Terminated" und "Resume" sind auch völlig legitim

- Wir wissen nur dass eine AV auftritt, nicht aber, welche Zeile der Debugger anmeckert


Vielleicht habe ich zu schlampig überflogen, aber der Code an sich ist doch korrekt, wenn man davon ausgeht dass die verwendete "UniDac"-Library das auch zulässt und nicht fordert, nur im Hauptthread ausgeführt zu werden.

Da einem alles um die Ohren fliegt ist die Annahme wohl nicht korrekt. Oder was übersehe ich?

Zacherl 21. Nov 2016 12:09

AW: Multithreading (Access Violation)
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1354277)
aber der Code an sich ist doch korrekt, wenn man davon ausgeht dass die verwendete "UniDac"-Library das auch zulässt und nicht fordert, nur im Hauptthread ausgeführt zu werden.

Da einem alles um die Ohren fliegt ist die Annahme wohl nicht korrekt. Oder was übersehe ich?

Sehe ich genauso :thumb:

Da nur eine einzige globale Instanz der
Delphi-Quellcode:
TMySQLUniProvider
Klasse erstellt wird, kann ich mir gut vorstellen, dass es hier kracht, wenn diese nicht thread-safe ist und die in den Threads erstellten Klassen da irgendwie indirekt drauf zugreifen.

taveuni 21. Nov 2016 12:25

AW: Multithreading (Access Violation)
 
Zitat:

Zitat von exchange (Beitrag 1354271)
Zum Testen while Schleife entfernt, sodass jeder Thread einmalig durchläuft.

Fehler bleibt.

Und welcher?

Ich verwende die Devart MySql und MSSql Libraries. Vermutich werden die Unidac ähnlich sein. Du kannst im Hauptthread eine Verbindung statisch oder dynamisch erzeugen. Dann diese in allen Threads Assignen. Dies nur als Info damit Du im Thread nicht jedesmal die Verbindungsdaten mitführen musst.

Delphi-Quellcode:

var
  Qry: TMSQuery;
  Conn: TMSConnection;
begin
  Conn:= TMSConnection.Create(Nil);
  Conn.Assign(FMyGlobalMsConnection);
  Qry:= TMSQuery.Create(Nil);
  Qry.Connection:= Conn;
  Try
    Try

    except
      on E: Exception do LogException(e, 'MyException');
    end;
  Finally
    Qry.Free;
    Conn.Free;
  End;

p80286 21. Nov 2016 15:16

AW: Multithreading (Access Violation)
 
Zitat:

Zitat von Zacherl (Beitrag 1354286)
Da nur eine einzige globale Instanz der
Delphi-Quellcode:
TMySQLUniProvider
Klasse erstellt wird, kann ich mir gut vorstellen, dass es hier kracht, wenn diese nicht thread-safe ist und die in den Threads erstellten Klassen da irgendwie indirekt drauf zugreifen.

Hab ich da was übersehen? In dem Zweiten Sourcecode hat jeder Thread eine eigene Connection und eine eigene Query?
Zitat:

Delphi-Quellcode:
procedure TThread1.Execute;
var DBConnection: TUniConnection; DBQuery: TUniQuery;
begin
   while not Terminated do
   begin
     DBConnection:=TUniConnection.Create(nil);
     DBConnection.Server:='172.16.6.50';
     DBConnection.Port:=3306;
     DBConnection.Username:='root_copy';
     DBConnection.Password:='password';
     DBConnection.ProviderName:='MySQL';
     DBConnection.Database:='testdb';

     DBConnection.Connect;

     if DBConnection.Connected then
     begin
         DBQuery:=TUniQuery.Create(nil);
         DBQuery.Connection:=DBConnection;
         DBQuery.SQL.Text:='INSERT into test SET datum=NOW(), thread=1;';
         DBQuery.Execute;
         DBQuery.Free;
       DBConnection.Close;
     end;

     DBConnection.Free;

     sleep(2000);
   end;
end;

Gruß
K-H

himitsu 21. Nov 2016 16:37

AW: Multithreading (Access Violation)
 
Zitat:

Zitat von p80286 (Beitrag 1354305)
Hab ich da was übersehen? In dem Zweiten Sourcecode hat jeder Thread eine eigene Connection und eine eigene Query?

Die Aussage bezog sich auf den Provider.
Delphi-Quellcode:
MySQL:=TMySQLUniProvider.Create(nil);

taveuni 21. Nov 2016 16:41

AW: Multithreading (Access Violation)
 
Aber das Ding wird in den Threads ja gar nicht benutzt? Oder habe ich Tomaten auf den Augen? Wofür ist das überhaupt?


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:36 Uhr.
Seite 2 von 3     12 3      

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