Bazı "FreeOnTerminate
" çalışan iş parçacığım var ve bunlar, yürütme bittiğinde yürütme ve kaldırma işleminden sonra, bir TThreadList
tanıtıcıları ekliyor. Ayrıca, çalışmalarını iptal etmeleri için onları uyabilecek bir global etkinlik nesnesini de kontrol ederler.Engelleme çağrısı sırasında bir kilit açma gerektiren bir durum nasıl ele alınır?
Ana parçacığı çalıştıran, olayı bildiren ve olası çalışan iş parçacıklarının sona ermesini bekleyen kısım aşağıdadır. WorkerHandleList
, global ThreadList
’dür.
...
procedure WaitForWorkers;
var
ThreadHandleList: TList;
begin
ThreadHandleList := TWorkerThread.WorkerHandleList.LockList;
TWorkerThread.WorkerHandleList.UnlockList;
WaitForMultipleObjects(ThreadHandleList.Count,
PWOHandleArray(ThreadHandleList.List), True, INFINITE);
end;
initialization
TWorkerThread.RecallAllWorkers := TEvent.Create;
TWorkerThread.WorkerHandleList := TThreadList.Create;
finalization
TWorkerThread.RecallAllWorkers.SetEvent;
WaitForWorkers;
TWorkerThread.RecallAllWorkers.Free;
TWorkerThread.WorkerHandleList.Free;
Bu tasarım, bence, ben ipler kendilerini aynı listeden kendi kolları kaldırmak beri bir kilitlenmeye neden olur çünkü sadece lifler kulpları bekleyen önce listeyi açmak zorunda bir kusur vardır . Herhangi bir kilit olmadan, bir içerik anahtarı, bir iş parçacığının kendisini serbest bırakmasına neden olabilir ve WAIT_FAILED
ile hemen geri dönmek için WaitForMultipleObjects
neden olur. WaitForMultipleObjects
engellediğinden ve kilitlemeyi ana iş parçacığından çıkaramayacağından başka bir kilit kullanamıyorum.
Bu tasarım, FreeOnTerminate
iş parçacığı kullanılmaması da dahil olmak üzere çeşitli şekillerde değiştirebilir, bunlar, serbest bırakılana kadar geçerli tanıtıcıları garanti eder. Veya iş parçacığı tutamaçlarının listesini yalnızca ana iş parçacığından değiştirerek. Ya da muhtemelen başkaları ...
Ama sormak istediğim, bu tür bir problemi, tasarımını değiştirmeden bir çözüm var mı? Örneğin, iş parçacığı iş parçacığının kodlarını listeden kaldırmadan önce mi yoksa SwitchToThread
numaralı telefonu arayarak çalışan olmayan tüm iş parçacıklarının çalıştırılmasına neden olur mu? Yeterince koşmak mı?
procedure WaitForWorkers;
var
ThreadHandleList: TList;
iItemCount : Integer;
begin
repeat
ThreadHandleList := TWorkerThread.WorkerHandleList.LockList;
try
iItemCount := ThreadHandleList.Count
finally
TWorkerThread.WorkerHandleList.UnlockList;
end;
if iItemCount = 0 then
BREAK;
sleep(Whatever_is_suitable);
until False;
end;
herhangi cpu döngülerinden olursa veya a, sorunu çözmek için basit yolu bu gibi olurdu (sadece ana iş parçacığı diğer yanında, ikincil olanları başlayacağı O) şeylerden kaç varsayarsak
bir [related soru] (http://stackoverflow.com/questions/8252804/when-to-free-a-thread-manually/8254173#8254173) (ı için ifadeleri gerekir ki Buradasınız). – NGLN