2009-06-24 20 views
6

Tôi có đoạn code sau (cắt giảm để có thể đọc):Will .Net Garbage Thu thập một đối tượng không được tham chiếu, nhưng có một chuỗi đang hoạt động?

Main Class:

public StartProcess() 
{ 
    Thinker th = new Thinker(); 
    th.DoneThinking += new Thinker.ProcessingFinished(ThinkerFinished); 
    th.StartThinking(); 
} 

void ThinkerFinished() 
{ 
    Console.WriteLine("Thinker finished"); 
} 

Thinker Class:

public class Thinker 
{ 
    private System.Timers.Timer t; 

    public delegate void ProcessingFinished(); 
    public event ProcessingFinished DoneThinking; 

    BackgroundWorker backgroundThread; 

    public Thinker() { } 

    public StartThinking() 
    { 
     t = new System.Timers.Timer(5000); // 5 second timer 
     t.AutoReset = false; 
     t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed); 
     t.Start(); 

     // start a background thread to do the thinking 
     backgroundThread = new BackgroundWorker(); 
     backgroundThread.DoWork += new DoWorkEventHandler(BgThread_DoWork); 
     backgroundThread.RunWorkerAsync(); 
    } 

    void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     DoneThinking(); 
    } 

    BgThread_DoWork(object sender, DoWorkEventArgs e) 
    { 
     // work in here should go for much less than 5 seconds 
     // it will die if it doesn't 

     t.Stop(); 
     DoneThinking(); 
    } 
} 

Những gì tôi ban đầu được dự kiến ​​sẽ xảy ra là người xử lý sự kiện trong lớp chính sẽ ngăn cản Nhà tư tưởng khỏi bị thu gom rác thải.

Apparently this isn't the case.

Tôi đang tự hỏi liệu việc thu gom rác có xảy ra bất kể chuỗi này có "bận" hay không. Nói cách khác, có một cơ hội nó sẽ được thu thập rác trước khi thời gian chờ 5 giây đã hết hạn?

Nói cách khác, người thu gom rác có thể thu thập Nhà tư tưởng của tôi trước khi xử lý xong không?

Trả lời

8

Không, chuỗi được xem là trực tiếp miễn là nó được tham chiếu, và bất kỳ chuỗi nào đang chạy được coi là tham chiếu (IIRC một chuỗi đang chạy đăng ký ngăn xếp của nó dưới dạng gốc GC và ngăn xếp đó sẽ tham chiếu chuỗi) .

Điều đó nói rằng tôi đang xem ví dụ của bạn và tôi không hiểu nơi bạn tin rằng một chuỗi đang được sinh ra?

+1

Khi sự kiện đã trôi qua trên Bộ hẹn giờ xảy ra, sự kiện xảy ra trên một chuỗi mới. Có lẽ đó là những gì anh ta đang nói về. http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx – Joe

+0

Xin lỗi, tôi không rõ ràng - đoạn nhận xét thực sự quan trọng hơn tôi đã cho nó tín dụng. Tôi sẽ cố gắng cập nhật. – Damovisa

+0

Ngoài ra, những gì Joe K nói - bản thân Timer tôi giả định sẽ chạy trên một chủ đề khác. Sự kiện đã trôi qua chắc chắn trở lại trên một chuỗi khác. – Damovisa

2

Nếu tôi đọc quyền này (và tôi có thể thoát ra khỏi đây), bạn có thể thu thập vì đó là không phải hiện đang làm bất kỳ điều gì.

Nếu bạn có biến cục bộ trong phương pháp bắt đầu và phương thức đó vẫn hoạt động, các biến đó vẫn sẽ là "trong phạm vi" trên ngăn xếp và cung cấp gốc cho chuỗi của bạn. Nhưng biến duy nhất bạn sử dụng là bộ đếm thời gian riêng tư của bạn và vì đó là bắt nguồn từ chính chuỗi và chuỗi không có gì trên ngăn xếp, không có gì còn lại để giữ cho nó luôn hoạt động.

+0

Điều tôi đang xem, nhưng Bộ hẹn giờ vẫn đang chạy. Không có nghĩa là lớp học vẫn còn sống? – Damovisa

+1

Bộ hẹn giờ không hoạt động. Khi bạn bắt đầu hẹn giờ, nó sẽ tạo một đối tượng trên một luồng khác và yêu cầu các cửa sổ đánh thức nó khi khoảng thời gian đã trôi qua. Không có gì còn lại trên luồng hiện tại. –

4

Không, ngăn xếp của chuỗi đang hoạt động là gốc cho mục đích GC. Ngăn xếp đó sẽ tồn tại miễn là Chủ đề đang chạy, do đó chính Chủ đề sẽ không được thu thập khi hoạt động của nó dài.

Dưới đây là một số article đề cập đến (trong số những thứ khác) nguồn gốc cho mục đích GC là gì. Để tiết kiệm thời gian, các gốc GC là các đối tượng toàn cầu, các đối tượng tĩnh, tất cả các tham chiếu trên tất cả các ngăn xếp luồng và tất cả các thanh ghi CPU chứa các tham chiếu.

0

Tôi đồng ý và không đồng ý, Nếu tham chiếu đến đối tượng chuỗi bị mất, chuỗi sẽ bị chấm dứt và thu thập rác. Trong trường hợp của bạn nó có thể không được như vậy bởi vì nó không trực tiếp sử dụng các chủ đề và đang sử dụng bộ đếm thời gian. Nhưng nếu bạn đã gọi phương thức trong chuỗi và tham chiếu chuỗi bị mất khi kết thúc phương thức thì nó sẽ được thu thập bởi GC

3

Câu hỏi của bạn hơi khó trả lời. Giống như Joel, theo như tôi có thể nói, bạn không có gì trên stack tham chiếu đến bộ hẹn giờ của bạn, mà chính nó là điều duy nhất tham chiếu đến chuỗi. Cho rằng, người ta sẽ mong đợi trường hợp Nhà tư tưởng sẽ được thu thập.

Tôi đã tò mò về điều này và cần giải thích cụ thể hơn về những gì có thể xảy ra, vì vậy tôi đào sâu vào Reflector một chút. Khi nó quay ra, System.Timers.Timer cuối cùng tạo ra một System.Threading.Timer, mà trong đó tạo ra một thể hiện của TimerBase, một lớp bên trong. TimerBase có nguồn gốc từ CriticalFinalizerObject, là một loại hệ thống đảm bảo rằng tất cả các mã trong một Vùng thực thi bị ràng buộc (CER) sẽ thực thi trước khi lớp thực thi được hoàn thành hoàn toàn và loại bỏ bởi GC. TimerBase cũng là IDisposable, và các vòng lặp phương thức vứt bỏ và spinwaits của nó cho đến khi khóa được giải phóng. Tại thời điểm này, tôi bắt đầu chạy vào mã bên ngoài, vì vậy tôi không chắc chắn chính xác cách khóa được khởi tạo hoặc phát hành.

Tuy nhiên, dựa trên cách lớp TimerBase được viết, thực tế là nó xuất phát từ CriticalFinalizerObject và thực tế là vứt bỏ spinwaits cho đến khi khóa được giải phóng, tôi nghĩ an toàn để nói rằng một chuỗi không được tham chiếu mọi thứ sẽ không được hoàn thành cho đến khi mã đó được thực hiện xong. Điều đó nói rằng ... điều quan trọng cần lưu ý là nó có khả năng sẽ được xử lý bởi GC ... khá có thể nhiều hơn một lần, như việc hoàn thiện có thể kéo dài quá trình thu thập trên các đối tượng đã hoàn thành. Đối với những người là CriticalFinalizerObjects, quá trình hoàn tất có thể mất nhiều thời gian hơn nếu có tích cực thực hiện mã mà CER đảm bảo sẽ thực hiện đầy đủ.

Điều đó có thể có nghĩa là bạn có chính xác vấn đề ngược lại nếu Nhà tư tưởng của bạn mất một lúc để thực thi. Thay vì những vật thể được thu thập sớm, họ sẽ đi vào một quyết toán dài, và bất cứ điều gì họ tham chiếu kết thúc trong gen2, và sống trong một thời gian cho đến khi GC cuối cùng có thể thu thập chúng hoàn toàn.

+0

Cảm ơn jrista - một số thứ tốt trong đó. Để tham khảo, chuỗi nền sẽ kết thúc gần như ngay lập tức nếu nó kết thúc ở tất cả. Nếu tôi hiểu câu trả lời của bạn một cách chính xác, Bộ hẹn giờ sẽ ngăn chặn việc thu gom rác sớm? – Damovisa

+0

Đúng, Bộ hẹn giờ nên ngăn chặn việc thu gom rác sớm. (Đó là trách nhiệm thực sự được giao cho System.Threading.TimerBase, do đó, một vài độ của nó loại bỏ, nhưng hiệu quả là như nhau.) – jrista

Các vấn đề liên quan