![]() |
Der Zugriff auf eine TSringList ist auf einmal nicht mehr möglixh
Hallo,
Titelwahl ist mir immer etwas schwer gefallen, aber ich versuche mal mein Problem genau zu schilder :stupid: Also, ich habe einen Service. Dort ist eine TStringList (genannt "MInfo") global deklariert. Es laufen insgesamt 3 Threads (Primärer Thread + 2 sekundäre Threads). Das sage ich extra dazu, weil die erste Reaktion wahrscheinlich wäre, das ich beim Threadhandling Mist gebaut habe, allerdings wird die StringList nur innerhalb eines Threads genutzt. Nun passiert folgendes: Eine Funktion wird ausgeführt (genannt RunCaptured) und wandelt den Inhalt einer PDF-Datei in Text um.
Delphi-Quellcode:
Das funktinoert auch alles wunderbar, am Ende wird mir im Log angezeigt, das MInfo 500 Zeilen hat.
function TEventThread.RunCaptured(const _dirName, _exeName,
_cmdLine: string): Boolean; var Start: TStartupInfo; procInfo: TProcessInformation; tmpName: string; tmp: THandle; tmpSec: TSecurityAttributes; res: TStringList; return: Cardinal; begin Result := False; try { Setze ein Temporäres File } { Set a temporary file } tmpName := 'Test.tmp'; FillChar(tmpSec, SizeOf(tmpSec), #0); tmpSec.nLength := SizeOf(tmpSec); tmpSec.bInheritHandle := True; tmp := CreateFile(PChar(tmpName), GENERIC_WRITE, File_Share_Write, @tmpSec, Create_Always, FILE_ATTRIBUTE_NORMAL, 0); try FillChar(Start, SizeOf(Start), #0); Start.cb := SizeOf(Start); Start.hStdOutput := tmp; Start.dwFlags := StartF_UseStdHandles or StartF_UseShowWindow; Start.wShowWindow := SW_Minimize; { Starte das Programm } { Start the program } if CreateProcess(nil, PChar(_exeName + ' ' + _cmdLine), nil, nil, True, CREATE_NO_WINDOW, nil, PChar(_dirName), Start, procInfo) then begin SetPriorityClass(procInfo.hProcess, Idle_Priority_Class); WaitForSingleObject(procInfo.hProcess, Infinite); GetExitCodeProcess(procInfo.hProcess, return); Result := (return = 0); CloseHandle(procInfo.hThread); CloseHandle(procInfo.hProcess); CloseHandle(tmp); { Die Ausgaben hinzufügen } { Add the output } res := TStringList.Create; try res.LoadFromFile(tmpName); MInfo.Clear; MInfo := res; // AUSGABE!!! Log(True, 'INFORMATION: Count of res = ' + IntToStr(res.Count) + '!'); Log(True, 'INFORMATION: Count of MInfo = ' + IntToStr(MInfo.Count) + '!'); // Anzahl der Zeilen in LogDatei speichern finally res.Free; end; DeleteFile(PChar(tmpName)); end else begin Log(True, 'ERROR: ' + PChar(SysErrorMessage(GetLastError()))); end; except on E: Exception do begin Log(True, Format('ERROR: [%s] "%s"', [E.Classname, E.Message])); CloseHandle(tmp); DeleteFile(PChar(tmpName)); end; end; finally end; end; Nach dem Ausführen dieser Routine wird eine weitere Routine augeführt, die folgendermassen anfängt:
Delphi-Quellcode:
In der im Code makierten zeile, kommt es zu einer EAccessViolation. Hier wollte ich nochmals die Anzahl der Zeilen von MInfo im Log speichern. Entferne ich diese Zeile kommt es in der nächsten Zeile aufgrund von "MInfo.Text" ebenfalls zu einer EAccessViolation. Ich kann mir aber nicht erklären warum! MInfo wird nur an diesen beiden Stellen verwendet. :?:
procedure TEventThread.ExtractInfo(JobID: Integer);
var s: String; i, j, k, l, EventID: Integer; begin LPuffer.Clear; LCourses.Clear; LCourses.CommaText := Jobs[JobID].Courses; Log(True, 'INFORMATION: Count of MInfo = ' + IntToStr(MInfo.Count) + '!'); // Hier kommt es zu einem Fehler! if ((MInfo.Text <> EmptyStr) and (LCourses.Count <> 0)) then // !!! begin {...} Hoffe jemand hat eine Idee :) [EDIT] Hier nochmal die Exception: "Zugriffsverletzung bei Adresse 00000000. Lesen von Adresse 00000000" Aber das hilft auch nicht viel weiter :/ Gruß, Lukas |
AW: Der Zugriff auf eine TSringList ist auf einmal nicht mehr möglixh
Delphi-Quellcode:
Du weist erst res zu MInfo zu und danach zerstörst Du die StringListe. Das ist beides die selbe Referenz! Verwende MInfo := res; // AUSGABE!!! <<<< Deswegen und... Log(True, 'INFORMATION: Count of res = ' + IntToStr(res.Count) + '!'); Log(True, 'INFORMATION: Count of MInfo = ' + IntToStr(MInfo.Count) + '!'); // Anzahl der Zeilen in LogDatei speichern finally res.Free; // <<<<<< ... Deswegen
Delphi-Quellcode:
oder stell Die Logik entsprechend um.
Assign
|
AW: Der Zugriff auf eine TSringList ist auf einmal nicht mehr möglixh
Wenn nur ein Thread diese StringList nutzt, warum ist die dann global deklariert und nicht privat innerhalb dieses Threads?
Dann kannst du dir sicher sein, dass kein anderer diese benutzt. |
AW: Der Zugriff auf eine TSringList ist auf einmal nicht mehr möglixh
In deiner Zeile
Delphi-Quellcode:
biegst du deine Referenz "Minfo" auf deine TStringList "res" um. Unter "res" und "Minfo" erreichst du jetzt ein und dieselbe TStringList. Und wenig später gibst du res frei. Dein "Minfo" zeigt jetzt auf einen Haufen Müll.
MInfo := res; // AUSGABE!!!
Wenn du jetzt später MInfo benutzt, knallt es. Du musst an dieser Stelle den Inhalt von "res" in "Minfo" vollständig kopieren. //Edit: Gott, was sind wir alle schnell :-) |
AW: Der Zugriff auf eine TSringList ist auf einmal nicht mehr möglixh
Zitat:
|
AW: Der Zugriff auf eine TSringList ist auf einmal nicht mehr möglixh
:wall: Klappt, super danke :) Hatte es sogar vorher richtig, habe es aber gestern geändert um was auszuprobieren und vergessen wieder rückgängig zu machen.
@SirRufo: Normalerweiße wird die StringList noch von einem anderen Thread verwendet, was ich aber bewusst verschwiegen habe, da der Thread im Moment nicht aktiv ist (Weil ich ihn schlicht und einfach für meine Testzwecke rausgenommen hab). |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:53 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