![]() |
Synchronize inerhalb globaler Funktion durchführen
Hallo,
ich habe ein gleines Synchronize Problem! Ich habe einen Thread der mir Daten in eine TThreadList reingibt oder rausnimmt. Der Thread ruft nun die LockList auf und befindet sich somit in der Critical Section. Wie kann ich aber nun in dieser Funktion auch noch die VCL updaten? Ein einfaches zugreifen auf das Memo in der VCL statt einem Synchronize führt zu Problemen da der Thread zwar gegen andere Threads sicher ist, aber nicht mit der VCL im Sync ist.
Delphi-Quellcode:
procedure RemoveData(Data : Pointer);
var List : TList; i : Integer; begin List := fStringList.LockList; try for i := 0 to List.Count - 1 do begin if List[i] = Data then begin List.Delete(i); ---> Synchronize(RemoveStringInMemo); ??????????????? end; end; finally fStringList.Unlocklist; end; end; |
AW: Synchronize inerhalb globaler Funktion durchführen
Also ich versteh das problem nicht ganz o.O.
Mal kurz zum mitschreiben: Du veränderst den inhalt einer stringlist, und nach dem manipulieren soll der inhalt mit dem Memo synchronisiert werden? Fals ich obiges richtig verstanden habe: Schreib ne prozedur die das macht und rufe die per Synchronize aus dem thread auf o.O MFG Memnarch |
AW: Synchronize inerhalb globaler Funktion durchführen
Man müsste jetzt noch sehen, wie RemoveStringInMemo herausfindet, welchen String es entfernen soll. Etwas mehr Code wäre hilfreich.
|
AW: Synchronize inerhalb globaler Funktion durchführen
Ich habe natürlich den Code oben nur kurz reingetippt ;)
Eigentlich ist die Funktion RemoveData in einer Class. Wird die Funktion RemoveData von einem Thread aufgerufen wird aus der TThreadList das Item entfernt. Danach wollte ich mit einer Funktion der Class ein Stringgrid in der Hauptform Updaten. Beim AutoSizeGrid (anpassen der GridSpaltenbreite) was beim Updaten ausgeführt wird gibt es aber dann Probleme. Ich habe jetzt auch versucht meiner Class den TThread zu übergeben, aber dann bekomme ich die Meldung das Synchronize protected ist. Also kann Synchronize nur im Thread selber aufgerufen werden. Ich hatte mir gedacht, ich kann eine Funktion machen, wo Daten der TThreadList bearbeitet werden und auch gleich das StringGrid in der VCL ein Update erhält. Nun glaube ich, dass ich halt im Thread die TThreadList bearbeiten muss und dann noch extra im Thread danach das Synchronize durchführen muss. |
AW: Synchronize inerhalb globaler Funktion durchführen
natürlich get Synchronize nur innerhalb eines Threads. Dieser funktion musst du dan die Funktion übergeben, die du synchronisieren möchtest(also z.B. die updatefunktion).
MFG Memnarch |
AW: Synchronize inerhalb globaler Funktion durchführen
Habe es nun so gemacht!
Ich gebe in eine Private Var meine Daten und rufe dann das Synchronize im Thread auf. Dies Sync Procedure ruft mit dann die Globale funktion auf und schraubt am StringGrid herum. Dann gibt es keine Probleme. Wie sieht es nun aus, wenn ein Thread das Synchronize ausführt und darin das LockList durchführt und nun ein anderer Thread auch das Synchronize ausführen will. Wartet da der zweite thread darauf, dass der erste die Sync Procedure wieder verlassen hat oder kann es hier einen Deadlock führen? |
AW: Synchronize inerhalb globaler Funktion durchführen
Ohne den konkreten Code, kann ich immer noch nur raten...
Aber: Wenn innerhalb RemoveStringInMemo ein LockList aufgerufen wird, darfst du während du das Synchronize aufrufst keien Lock auf die Liste haben, sonst ahst du schon deinen DeadLock. Durch das Synchronize ist dein Thread blockiert und im HauptThread geht das Lock nicht durch. Wenn immer nur ein Element aus der Liste entfernt wird, merk dir doch den Index und ruf Synchronize nach dem Unlock auf. Eventuell kannst du auch statt Synchronize Queue aufrufen, aber das kann dann ganz andere Nebeneffekte haben. Es gibt eben keine generelle Regel. |
AW: Synchronize inerhalb globaler Funktion durchführen
TThread bietet Synchronize in mehreren Varianten, einige als Klassen-Methode, welche man direkt über
Delphi-Quellcode:
nutzen kann.
TThread.Synchronize(nil, MyProc);
Entweder mit einer Prozedur ( ![]() oder als Methode ( ![]() |
AW: Synchronize inerhalb globaler Funktion durchführen
Zitat:
Eine CriticalSection darf unter der gleichen ThreadID sooft betreten werden wie man lustig ist. Und wenn der Aufruf per Sync erfolgt, dann befindest du dich im Kontext von MainThreadID! Somit bringt dir die CriticalSection da nix ausser verschwendete Bytes im Source und Code. Wer es nicht glaubt ;) das geht und wird auch immer brav aufgerufen
Delphi-Quellcode:
Es ist auch immer hilfreich an gewissen Stellen mit OutputDebugString oder dem Schreiben einer Log-Datei oder mit einem Haltepunkt im Debugger die Statuswerte zu prüfen.
procedure RemoveData(Data : Pointer);
var List : TList; i : Integer; begin // Da aus dem Thread mit Sync aufgerufen wird // ist diese Bedingung immer erfüllt // und kann daher auch entsorgt werden if MainThreadID = GetCurrentThreadID then begin for i := 0 to List.Count - 1 do begin if List[i] = Data then begin List.Delete( i ); // Hier noch der Aufruf zur Aktualisierung des Memos end; end; end; end; (z.B. GetCurrentThreadID und MainThreadID ;) ) |
AW: Synchronize inerhalb globaler Funktion durchführen
Zitat:
Also wenn ein Thread ein LockList macht, dann sollte er das am Ende auch wieder freigeben und nachdem dieser Synchronizeaufruf fertig abgearbeitet wurde, erst dann wird das andere Synchornize ausgefphrt und die Liste wäre ja schonwieder frei. Gut, und zusärtlich das schon erwähnte Verhalten der CS, welche praktisch nur für andere Threads sperrt ... Synchronize-Prozeduren laufen ja immer im Hauptthread (dem der VCL) ab. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:22 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