AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

StringGrid.Create threadsicher?

Ein Thema von Ykcim · begonnen am 28. Nov 2024 · letzter Beitrag vom 2. Dez 2024
Antwort Antwort
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
831 Beiträge
 
Delphi 10.4 Sydney
 
#1

StringGrid.Create threadsicher?

  Alt 28. Nov 2024, 17:43
Hallo Zusammen,

ich habe ein etwas kompliziertes Konstrukt:
Thread1 prüft alle 60 Sekunden, ob die Zeit für einen oder mehrere Berichte erreicht wird.
--> Wenn True, dann erstellt Thread1 so viele Threads, wie Berichte erstellt werden sollen. Wir nennen sie Thread2
--> Dabei wird für jeden Thread ein ReportObject created, durch welches der Report erstellt wird.

Von Thread2 können also beliebig viele parallel laufen.

Thread2 lässt das ReportObject den Bericht erstellen. Dabei wird am Anfang immer ein TAdvStringGrid (TMS Components) erstellt, dass am Ende der Berichtserstellung mit Daten gefüllt wird, und das am Ende eine formatierte Excel-Datei absprichert und per Mail versendet. Das StringGrid wird nie irgendwo in einer Form gezeigt, sondern ist nur virtuell.

Und bei dem TAdvStringGrid.Create(nil) kommt es in unregelmäßigen Abständen zu Exceptions, bei denen ich keinen Zusammenhang erkennen kann. Es kann sein, dass das Ganze fünf Mal problemlos klappt und beim sechsten Mal kommt immer an dieser Stelle eine Exception:
Zitat:
Zugriffsverletzung bei Adresse 0047F999 in Modul 'BD_VersandServer.exe'. Lesen von Adresse 00000008
Jetzt habe ich mir überlegt, dass StringGrid.Create vielleicht nicht threadsicher ist und habe in dem ReportObject ein privates DatenGrid: TAdvStringGrid definiert, welches ich immer beim Create des ReportObjectes mit create. Da das ReportObject eine Variable des Thread2 ist und im Zuge der Erstellung des Thread2 auch erstellt wird, passiert das hübsch nacheinander und nicht zeitgleich.

Delphi-Quellcode:
for I := 1 to Length(fSections) -1 do begin //Erster Eintrag ist Überschrift der INI-Datei
               LogText:= Logic.SetLogText_CR(JSValCRSet.GetValue<string>(fSections[0] + '.' + fSections[I] + '[0].ReportName'), JSValCRSet.GetValue<string>(fSections[0] + '.' + fSections[I] + '[0].KundenNr'), '', 57);
               ///Daily Reports
               if JSValCRSet.GetValue<string>(fSections[0] + '.' + fSections[I] + '[0].Activ') = '1then begin
                  if JSValCRSet.GetValue<string>(fSections[0] + '.' + fSections[I] + '[0].RepeatInterv') = 'dailythen begin
                     SendTime:= FormatDateTime ('hh:nn', Now);
                     SendDay:= FormatDateTime ('dddd', Now);
                     VDay:= FormatDateTime ('dddd', Now);
                     VZeit:= JSValCRSet.GetValue<string>(fSections[0] + '.' + fSections[I] + '[0].DailyTime');
                     if (JSValCRSet.GetValue<string>(fSections[0] + '.' + fSections[I] + '[0].Weekend') = '1') or //Wenn Weekend = 1 immer ausführen
                        ((JSValCRSet.GetValue<string>(fSections[0] + '.' + fSections[I] + '[0].Weekend') = '0') and //Wenn Weekend = 0 nur Mo - Fr
                           ((VDay <> 'Samstag') and
                              (VDay <> 'Sonntag'))) then begin //Ohne Wochenende
                        if (Pos(SendTime, VZeit) > 0) then begin
                           J:= Length(ArryRprtThrd) -1;
                           SetLength(ArryRprtThrd, J + 1);
                           Logic.SendLogMessage(fWriteCRLog, LogText + ' STARTED', fCRMemoName);
                           //Report Execute-Thread erstellen
                           ArryRprtThrd[J]:= TThreadExcCstRprts.Create(true);
                           ArryRprtThrd[J].FreeOnTerminate:= true;
                           ArryRprtThrd[J].JSValGenSet:= fJSValGenSet;
                           ArryRprtThrd[J].Report:= TRprtCrtr.Create(fJSValGenSet, JSValCustSet, JSValCRSet, fWriteCRProt, fWriteCRLog, fCRMemoName, fMailSGName); //ReportObject
                           ArryRprtThrd[J].ReportID:= fSections[I];
                           ArryRprtThrd[J].KdNr:= JSValCRSet.GetValue<string>(fSections[0] + '.' + fSections[I] + '[0].KundenNr');
                           ArryRprtThrd[J].CRMemoName:= fCRMemoName;
                           ArryRprtThrd[J].CRSGName:= fCRSGName;
                           ArryRprtThrd[J].WriteCRProt:= fWriteCRProt;
                           ArryRprtThrd[J].WriteCRLog:= fWriteCRLog;
                           ArryRprtThrd[J].Resume;
                        end
                        else begin
                           //Logic.SendLogMessage(fWriteCRLog, LogText + ' CHECKED', fCRMemoName);
                        end;
                     end
                     else begin
                        Logic.SendLogMessage(fWriteCRLog, 'No Check by Weekend', fCRMemoName);
                     end;
                  end
Durch die For-Schleife, in der die Thread2 erstellt werden, werden diese schön nacheinander erstellt und das TAdvStringGrid.Create wird nicht parallel aufgerufen...

Create des ReportObject jetzt mit Create des privaten StringGrids
Delphi-Quellcode:
constructor TRprtCrtr.Create(JSValueGenSet, JSValueCustSet, JSValueCRSet: TJSONValue; WriteCRProt: TWriteCRProt; WriteCRLog: TWriteCRLog; mmName, SGName: string);
begin
   if Assigned(JSValueCRSet) then
      SetJSValCRSet(JSValueCRSet);
   if Assigned(JSValueCustSet) then
      SetJSValCustSet(JSValueCustSet);
   if Assigned(JSValueGenSet) then
      SetJSValGenSet(JSValueGenSet);
   if (Assigned(WriteCRProt)) and (SGName <> '') then
      SetWriteCRProt(WriteCRProt);
   if (Assigned(WriteCRLog)) and (mmName <> '') then
      SetWriteCRLog(WriteCRLog);
   SetmmName(mmName);
   SetSGName(SGName);
   fSGReportDaten:= TAdvStringGrid.Create(nil);
end;
Im ersten Test hat es geklappt, aber ich wollte Euch fragen, ob Ihr wisst, ob StringGrid.Create threadsicher ist oder nicht.

Vielen Dank
Patrick
Patrick

Geändert von Ykcim (28. Nov 2024 um 17:54 Uhr)
  Mit Zitat antworten Zitat
taveuni

Registriert seit: 3. Apr 2007
Ort: Zürich
534 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: StringGrid.Create threadsicher?

  Alt 28. Nov 2024, 18:58
Ja wir wissen es: die VCL ist nicht Threadsafe.
Die obige Aussage repräsentiert meine persönliche Meinung.
Diese erhebt keinen Anspruch auf Objektivität oder Richtigkeit.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: StringGrid.Create threadsicher?

  Alt 28. Nov 2024, 19:11
Und die meisten VCL-Objekte (die mit einem HWND) sind auch noch thread-affine.

Ihre Messages werden nur über die Thread-MessageQueue behandelt, in dessen Thread sie erstellt wurden.


A: VCL ist nicht thread-save ... es werden öfters globale Default-Sachen gemeinsam verwendndet, wie z.B. in TFont, TPen und TBrush.

B: ein VCL-Objekt muß auch im VCL-Thread (MainThread) erstellt werden. (da du bestimmt vergessen hast die Message-Queue deines Threads abzuarbeiten)

C: Sowas mach man einfach nicht.


Es gibt einige Komponenten, die kann man teilweise in einem Thread behandeln. (nicht erstellen/freigeben ... nur auf gewisse Teile drauf zugreifen)
z.B. ein Bitmap/Image/Canvas, so lange das Canvas gesperrt wurde,
oder eine ListBox mit BeginUpdate (natürlich im Hauptthread ausgeführt)




-> TThread.Syncronize und TThread.Queue

SendMessage und PostMessage syncronisieren sich selbst, in den Thread, wo die Empfänger-Komponente erstellt wurde.
$2B or not $2B

Geändert von himitsu (28. Nov 2024 um 19:17 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#4

AW: StringGrid.Create threadsicher?

  Alt 28. Nov 2024, 22:04
C: Sowas mach man einfach nicht.
... und sowas:
Das StringGrid wird nie irgendwo in einer Form gezeigt, sondern ist nur virtuell.
macht man übrigens auch nicht.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Sinspin
Sinspin

Registriert seit: 15. Sep 2008
Ort: Dubai
691 Beiträge
 
Delphi 10.3 Rio
 
#5

AW: StringGrid.Create threadsicher?

  Alt 29. Nov 2024, 08:05
Da gibt es doch sicherlich eine bessere Option um eine Excel-Tabelle zu erstellen? Du musst dafür doch keine sichtbare Komponente verwenden.
Ich kenne TMS nicht, aber die haben vermutlich, genau wie DevExpress, Excel als Document-Schnittstelle.
Stefan
Nur die Besten sterben jung
A constant is a constant until it change.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#6

AW: StringGrid.Create threadsicher?

  Alt 29. Nov 2024, 10:17
Dafür gibt es bei TMS doch FlexCel (https://www.tmssoftware.com/site/flexcel.asp) und dort bietet sich insbesondere die TXlsFile Klasse an.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
831 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: StringGrid.Create threadsicher?

  Alt 2. Dez 2024, 08:53
Guten Morgen Zusammen,

offensichtlich habe ich hier gefuscht... Ich habe eine Klasse, mit der ich den Export von Grids mache, was ja auch ok ist. Aber anscheinend nur, wenn sie im HauptThread ausgeführt wird und wenn es auch ein "echtes" Grid ist... da ist es verlockend, es auch bei virtuellen Grids zu nutzen...

Vielen Dank, dass Ihr mir das erklärt habt. Ich habe am Freitag versucht, es umzubauen (tatsächlich mit TMS FlexCel), habe aber gerade noch Schwierigkeiten, dass der Stream nicht gelesen werden kann.

Ich gucke mal, ob es mir heute gelingt.

Vielen Dank für das Input!

LG Patrick
Patrick
  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 11:45 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