2013-02-13 26 views
8

xem xét mã này:Làm thế nào để có được những mục tiêu của một tham chiếu yếu trong một cách an toàn

var weakRef = new WeakReference(new StringBuilder("Mehran")); 
if (weakRef.IsAlive) 
{ 
    // Garbage Collection might happen. 
    Console.WriteLine((weakRef.Target as StringBuilder).ToString()); 
} 

Có thể cho GC.Collect để chạy sau khi kiểm tra weakRef.IsAlive và trước khi sử dụng weakRef.Target.

Tôi có sai với điều này không? Nếu nó có thể, ss có một cách an toàn để làm điều đó?

Ví dụ: API như weakRef.GetTargetIfIsAlive() sẽ phù hợp.

+1

Kiểm tra http://msdn.microsoft.com/en-gb/library/ms404247.aspx –

+1

Trước tiên, bạn nên truyền tới tham chiếu mạnh và sau đó kiểm tra 'null'. Không có cách nào bạn có thể đảm bảo tài liệu tham khảo mạnh mẽ của bạn sẽ không được null trước. –

Trả lời

12

API đó đã tồn tại; weakRef.Target trả về null nếu đối tượng đã được thu gom rác.

StringBuilder sb = weakRef.Target as StringBuilder; 
if (sb != null) 
{ 
    Console.WriteLine(sb.ToString()); 
} 
1

Lấy bản sao cục bộ của mục tiêu và kiểm tra giá trị rỗng.

WeakReference.Target sẽ trả lại null nếu mục tiêu đã được thu thập nhưng bạn lo ngại rằng nó được thu thập giữa số .IsAlive kiểm tra và nhận mục tiêu.

var weakRef = new WeakReference(new StringBuilder("Mehran")); 

if (weakRef.IsAlive) 
{ 
    var stringBuilder = weakRef.Target as StringBuilder; 

    if (stringBuilder != null) 
    { 
     Console.WriteLine(stringBuilder.ToString()); 
    } 
} 

Console.WriteLine((weakRef.Target as StringBuilder).ToString()); sẽ ném một ngoại lệ tham chiếu null nếu phôi không thành công.

+0

Tôi đã tự hỏi tại sao kiểm tra 'weakRef.IsAlive' là bắt buộc, @supercat trả lời câu hỏi, vì vậy tôi nghĩ rằng việc kiểm tra nó là không cần thiết. – mehrandvd

+1

@mehrandvd Có thể không cần thiết, tôi chỉ sử dụng nó trong ví dụ này vì nó dựa trên câu hỏi ban đầu của bạn. Nó không thể làm hại gì để sử dụng nó nhưng có thể nó là một kiểm tra vô nghĩa cho phép kiểm tra 'as' và null trên' .Target'. –

+1

@TrevorPilley: Sử dụng 'IsAlive' trên' WeakReference' nếu giá trị 'true' có nghĩa là một giá trị muốn lấy mục tiêu là vô nghĩa. Có thể với một số người thu gom rác, sử dụng 'if (wr1.IsAlive && wr2.IsAlive && wr3.IsAlive) {Foo wt1 = wr1.Target là Foo, wt2 = wr2.Target là Foo, wt3 = wr3.Target là Foo; if (wr1! = null && wr2! = null && wr3! = null) {... sử dụng cả ba thứ ...} 'có thể hữu ích nếu ví dụ: một bộ thu gom rác đồng thời hoạt động bằng cách theo dõi xem liệu một tham chiếu đến một cái gì đó đã được tạo ra từ GC cuối cùng chưa. Trên một GC như vậy, nếu wr3 đã chết nhưng wr1 và wr2 vẫn còn sống ... – supercat

9

Thuộc tính IsAlive không tồn tại vì lợi ích của mã sẽ muốn sử dụng mục tiêu nếu nó còn sống, trong việc truy cập nó trong mọi trường hợp. Nếu mã được kiểm tra Target đối với null, điều đó có thể gây ra Target trong giây lát có tham chiếu bắt nguồn (mã được thử nghiệm với null) và có thể hành vi tạo tham chiếu bắt nguồn như vậy có thể ngăn không cho đối tượng bị thu gom rác nếu không thì sẽ như vậy. Nếu mã không quan tâm đến Target ngoại trừ để tìm hiểu xem mã đó có bị vô hiệu hay không, không có lý do gì để mã tham chiếu. Nó có thể chỉ cần kiểm tra IsAlive thay vào đó và thực hiện hành động phù hợp nếu nó trả về false.

+0

Tôi đã tự hỏi tại sao 'IsAlive' tồn tại. Đây là một câu trả lời rất thông minh, Cảm ơn. – mehrandvd

+1

@mehrandvd: Không khó để tưởng tượng một GC đồng thời trong đó hành động tìm nạp 'Mục tiêu' từ' WeakReference' sẽ ngăn đối tượng đó thu thập trong chu kỳ tiếp theo * ngay cả khi tham chiếu bị hủy ngay lập tức *.Trên một hệ thống như vậy, mã muốn thực hiện một số hành động ngay sau khi một đối tượng không còn cần thiết và sử dụng 'Mục tiêu' thay vì' IsAlive' có thể kết thúc việc giữ đối tượng đang nghi vấn tồn tại mãi mãi. – supercat

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