Bạn không thể đặt FreeOnTerminate
-True
và gọi Free
trên dụ chủ đề. Bạn phải làm một cái khác, nhưng không phải cả hai. Vì nó đứng mã của bạn phá hủy các chủ đề hai lần. Bạn không bao giờ phải phá hủy một đối tượng hai lần và tất nhiên khi destructor chạy lần thứ hai, các lỗi xảy ra.
Điều xảy ra ở đây là vì bạn đã tạo chuỗi bị treo, không có gì xảy ra cho đến khi bạn giải phóng hoàn toàn chuỗi. Khi bạn làm điều đó, destructor sẽ tiếp tục lại luồng, đợi nó hoàn tất. Điều này sau đó dẫn đến việc Free
được gọi lại vì bạn đặt FreeOnTerminate
thành True
. Lệnh gọi thứ hai này để Free
đóng tay cầm. Sau đó, bạn quay lại chủ đề proc và gọi số ExitThread
. Điều này không thành công vì xử lý của chuỗi đã bị đóng.
Như Martin chỉ ra trong nhận xét bạn không được tạo TThread
trực tiếp vì phương pháp TThread.Execute
là trừu tượng. Ngoài ra, bạn không nên sử dụng Resume
không được dùng nữa. Sử dụng Start
để bắt đầu thực hiện một chuỗi bị treo.
Cá nhân tôi không thích sử dụng FreeOnTerminate
. Sử dụng tính năng này dẫn đến việc chuỗi bị hủy trên một chuỗi khác mà từ đó nó được tạo ra. Bạn thường sử dụng nó khi bạn muốn quên tham chiếu cá thể. Điều đó sau đó khiến bạn không chắc chắn liệu chuỗi có bị hủy hay không khi quá trình của bạn chấm dứt, hoặc thậm chí là nó chấm dứt và giải phóng chính nó trong quá trình chấm dứt quá trình.
Nếu bạn phải sử dụng FreeOnTerminate
thì bạn cần đảm bảo rằng bạn không gọi Free
sau khi đã đặt FreeOnTerminate
thành True
. Vì vậy, giải pháp hiển nhiên là đặt FreeOnTerminate
thành True
ngay trước khi gọi Start
và sau đó quên về phiên bản chuỗi. Nếu bạn có bất kỳ ngoại lệ nào trước khi bạn sẵn sàng bắt đầu thì bạn có thể giải phóng một cách an toàn chuỗi đó vì bạn FreeOnTerminate
vẫn sẽ là False
tại thời điểm đó.
Thread := TMyThread.Create(True);
Try
//initialise thread object
Except
Thread.Free;
raise;
End;
Thread.FreeOnTerminate := True;
Thread.Start;
Thread := nil;
Cách tiếp cận thanh lịch hơn là di chuyển tất cả việc khởi tạo vào công cụ xây dựng TMyThread
. Sau đó, mã sẽ trông giống như sau:
Thread := TMyThread.Create(True);
Thread.FreeOnTerminate := True;
Thread.Start;
Thread := nil;
Nguồn
2012-01-10 15:44:47
Trước tiên, bạn có nhận được bất kỳ lỗi/cảnh báo nào về điều này không? TThread.Execute là trừu tượng trong D2009. IME, bạn sẽ nhận được một cảnh báo về việc xây dựng các cá thể với các phương thức trừu tượng. Thông thường, TThread.Execute được ghi đè trong lớp hậu duệ TThread và đó là hậu duệ được khởi tạo. Tôi đã không bao giờ cố gắng để tạo ra một thể hiện của TThread trực tiếp - Tôi khá chắc chắn rằng một số ngoại lệ sẽ được nâng lên trên thread xây dựng, các thread xây dựng hoặc cả hai. –
Bạn có thể đợi để đặt 'FreeOnTerminate' cho đến trước khi bạn gọi' Tiếp tục'. –
Tôi đoán hủy các cuộc gọi tiếp tục vì nếu một sợi bị treo thì nó không thể bị phá hủy đúng cách trong trạng thái như vậy. –