Tôi có một ứng dụng Delphi mà sinh ra 6 chủ đề ẩn danh khi một số sự kiện TTimer.OnTimer.Làm thế nào để chấm dứt chủ đề vô danh trong Delphi trên ứng dụng đóng?
Nếu tôi đóng ứng dụng từ nút X trong thanh tiêu đề Truy cập vi phạm tại địa chỉ $ C0000005 được nêu ra và báo cáo FastMM bị rò rỉ đối tượng TAnonymousThread.
Cách tốt nhất để giải phóng các chuỗi ẩn danh trong Delphi được tạo trong sự kiện OnTimer bằng phương thức TThread.CreateAnonymousThread() là gì?
SOLUTION mà làm việc cho tôi:
tạo một wrapper của bài nặc danh mà chấm dứt họ khi là miễn phí-ed.
type
TAnonumousThreadPool = class sealed(TObject)
strict private
FThreadList: TThreadList;
procedure TerminateRunningThreads;
procedure AnonumousThreadTerminate(Sender: TObject);
public
destructor Destroy; override; final;
procedure Start(const Procs: array of TProc);
end;
{ TAnonumousThreadPool }
procedure TAnonumousThreadPool.Start(const Procs: array of TProc);
var
T: TThread;
n: Integer;
begin
TerminateRunningThreads;
FThreadList := TThreadList.Create;
FThreadList.Duplicates := TDuplicates.dupError;
for n := Low(Procs) to High(Procs) do
begin
T := TThread.CreateAnonymousThread(Procs[n]);
TThread.NameThreadForDebugging(AnsiString('Test thread N:' + IntToStr(n) + ' TID:'), T.ThreadID);
T.OnTerminate := AnonumousThreadTerminate;
T.FreeOnTerminate := true;
FThreadList.LockList;
try
FThreadList.Add(T);
finally
FThreadList.UnlockList;
end;
T.Start;
end;
end;
procedure TAnonumousThreadPool.AnonumousThreadTerminate(Sender: TObject);
begin
FThreadList.LockList;
try
FThreadList.Remove((Sender as TThread));
finally
FThreadList.UnlockList;
end;
end;
procedure TAnonumousThreadPool.TerminateRunningThreads;
var
L: TList;
T: TThread;
begin
if not Assigned(FThreadList) then
Exit;
L := FThreadList.LockList;
try
while L.Count > 0 do
begin
T := TThread(L[0]);
T.OnTerminate := nil;
L.Remove(L[0]);
T.FreeOnTerminate := False;
T.Terminate;
T.Free;
end;
finally
FThreadList.UnlockList;
end;
FThreadList.Free;
end;
destructor TAnonumousThreadPool.Destroy;
begin
TerminateRunningThreads;
inherited;
end;
End ở đây là làm thế nào bạn có thể gọi nó là:
procedure TForm1.Button1Click(Sender: TObject);
begin
FAnonymousThreadPool.Start([ // array of procedures to execute
procedure{anonymous1}()
var
Http: THttpClient;
begin
Http := THttpClient.Create;
try
Http.CancelledCallback := function: Boolean
begin
Result := TThread.CurrentThread.CheckTerminated;
end;
Http.GetFile('http://mtgstudio.com/Screenshots/shot1.png', 'c:\1.jpg');
finally
Http.Free;
end;
end,
procedure{anonymous2}()
var
Http: THttpClient;
begin
Http := THttpClient.Create;
try
Http.CancelledCallback := function: Boolean
begin
Result := TThread.CurrentThread.CheckTerminated;
end;
Http.GetFile('http://mtgstudio.com/Screenshots/shot2.png', 'c:\2.jpg');
finally
Http.Free;
end;
end
]);
end;
Không rò rỉ bộ nhớ, tắt máy phù hợp và dễ sử dụng.
'chủ đề ẩn danh' - Tuyệt vời .. Embarcadero đã bỏ mặc gì cho chúng tôi bây giờ? –
@Martin: Không có gì đáng sợ, thực sự. Đó là một luồng có hành vi được cung cấp tại thời điểm tạo bởi một phương thức ẩn danh. Nó cho phép bạn sử dụng các bao đóng khi định nghĩa các luồng. –
Nó liên tục tạo ra/phá hủy các chủ đề, một cái gì đó tôi đã dành 20 năm qua nói với các nhà phát triển để tránh. Tuy nhiên, nếu không thực sự bắt đầu, tôi không thể thấy tại sao nên có một AV. –