![]() |
StringGrid.Create threadsicher?
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:
Delphi-Quellcode:
Durch die For-Schleife, in der die Thread2 erstellt werden, werden diese schön nacheinander erstellt und das TAdvStringGrid.Create wird nicht parallel aufgerufen...
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') = '1' then begin if JSValCRSet.GetValue<string>(fSections[0] + '.' + fSections[I] + '[0].RepeatInterv') = 'daily' then 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 Create des ReportObject jetzt mit Create des privaten StringGrids
Delphi-Quellcode:
Im ersten Test hat es geklappt, aber ich wollte Euch fragen, ob Ihr wisst, ob StringGrid.Create threadsicher ist oder nicht.
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; Vielen Dank Patrick |
AW: StringGrid.Create threadsicher?
Ja wir wissen es: die VCL ist nicht Threadsafe.
|
AW: StringGrid.Create threadsicher?
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. |
AW: StringGrid.Create threadsicher?
Zitat:
Zitat:
|
AW: StringGrid.Create threadsicher?
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. |
AW: StringGrid.Create threadsicher?
Dafür gibt es bei TMS doch FlexCel (
![]() |
AW: StringGrid.Create threadsicher?
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 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:35 Uhr. |
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