2009-02-20 44 views
10

Tôi có một đối tượng đắt tiền để tạo, sử dụng một số tài nguyên không được quản lý phải được giải phóng một cách rõ ràng khi được thực hiện và vì vậy hãy triển khai IDisposable(). Tôi muốn một bộ nhớ cache ví dụ của các nguồn tài nguyên đắt tiền để chi phí tạo ra được giảm thiểu, nhưng tôi gặp khó khăn khi biết làm thế nào để đối phó với việc xử lý.Làm cách nào để quản lý các đối tượng IDisposable được lưu trong bộ nhớ cache?

Nếu các phương pháp sử dụng các đối tượng chịu trách nhiệm xử lý thì tôi kết thúc với các trường hợp được xử lý trong bộ nhớ cache, sau đó phải được tạo lại, đánh bại điểm của bộ nhớ cache. Nếu tôi không vứt bỏ các đối tượng trong các phương pháp sử dụng chúng thì chúng sẽ không bao giờ bị xử lý. Tôi nghĩ rằng tôi có thể vứt bỏ chúng khi chúng được lấy ra khỏi bộ nhớ cache, nhưng sau đó tôi có thể kết thúc xử lý một thể hiện mà vẫn đang được sử dụng bởi một phương pháp.

Có hợp lệ để chỉ cho phép chúng vượt quá phạm vi và được thu thập bởi bộ thu gom rác và giải phóng tài nguyên tại thời điểm đó không? Điều này cảm thấy sai và chống lại ý tưởng của họ đang được dùng một lần ...

Trả lời

4

Đối tượng dùng một lần luôn cần có chủ sở hữu rõ ràng chịu trách nhiệm xử lý chúng. Tuy nhiên, đây không phải lúc nào cũng là đối tượng tạo ra chúng. Hơn nữa, quyền sở hữu có thể được chuyển giao.

Nhận ra điều này, giải pháp trở nên rõ ràng. Không vứt bỏ, tái chế! Bạn không chỉ cần một cách để có được một nguồn tài nguyên từ bộ nhớ cache, mà còn là một cách để trả lại nó. Tại thời điểm đó bộ nhớ cache là chủ sở hữu một lần nữa, và có thể chọn để giữ lại các nguồn lực để sử dụng trong tương lai hoặc để xử lý nó.

public interface IDisposableItemCache<T> : IDisposable 
     where T:IDisposable 
    { 
     /// <summary> 
     /// Creates a new item, or fetches an available item from the cache. 
     /// </summary> 
     /// <remarks> 
     /// Ownership of the item is transfered from the cache to the client. 
     /// The client is responsible for either disposing it at some point, 
     /// or transferring ownership back to the cache with 
     /// <see cref="Recycle"/>. 
     /// </remarks> 
     T AcquireItem(); 

     /// <summary> 
     /// Transfers ownership of the item back to the cache. 
     /// </summary> 
     void Recycle(T item); 

    } 

chỉnh sửa: Tôi chỉ nhận thấy rằng ý tưởng này cũng tồn tại trong mùa xuân, nơi nó được gọi là một object pool. Các phương thức BorrowObjectReturnObject của chúng tôi phù hợp với các phương pháp trong ví dụ của tôi.

+0

Tôi về cơ bản đã kết thúc với một giải pháp đó là một lai của câu trả lời này và NoBugz. Cảm ơn –

2

Bạn có thể tách các tài nguyên không được quản lý khỏi cá thể được quản lý và sử dụng trình quản lý bộ nhớ cache để giữ một tập hợp các tài nguyên không được quản lý. Đối tượng được quản lý sẽ cố gắng lấy một thể hiện của tài nguyên không được quản lý từ trình quản lý bộ nhớ cache để tạo một hoặc cung cấp một cá thể miễn phí từ bộ nhớ cache và trả về trình quản lý bộ nhớ cache (thay vì xử lý nó) tại thời điểm xử lý . Trình quản lý bộ nhớ cache sẽ là đối tượng chịu trách nhiệm duy nhất để phân bổ và giải phóng tài nguyên không được quản lý khi thấy cần thiết.

3

Trước hết, loại kết thúc tốt đẹp các tài nguyên gốc phải được hoàn thiện, không chỉ dùng một lần. Thậm chí tốt hơn, sử dụng SafeHandle để bao bọc các tài nguyên gốc.

Trừ khi ai đó có trách nhiệm rõ ràng khi nói rằng chúng được thực hiện với mục và nó có thể được xử lý, sau đó tôi nghĩ bạn nên để cho GC chăm sóc nó. Lưu ý rằng nó phải được finalizable mặc dù, nếu không GC sẽ không cho nó một cái nhìn thứ hai.

4

Để (mis-) quote Raymond Chen: Mỗi bộ nhớ cache mà không có một chính sách hết hạn là một sự rò rỉ

Vì vậy, thiết lập một chính sách rõ ràng bộ nhớ cache hết hạn, và để cho bộ nhớ cache xử lý chúng như trường hợp bình thường. Điều này vẫn còn tắt ứng dụng để được xử lý.

Nếu tài nguyên không được quản lý của bạn thuộc sở hữu của quy trình, bạn có thể để quy trình giải phóng chúng khi tắt máy.

Nếu tài nguyên không được quản lý là không phải là thuộc sở hữu của quy trình, bạn cần phải phát hiện tắt máy và loại bỏ rõ ràng các yếu tố được lưu trong bộ nhớ cache.

Nếu bạn không thể phát hiện quá trình tắt máy một cách đáng tin cậy và các tài nguyên được quản lý tốn kém, những tài nguyên không được quản lý sẽ không tách rời khỏi các tài nguyên không được quản lý và để bộ nhớ cache chỉ giữ lại các tài khoản được quản lý.

Khi các tài nguyên không được quản lý tốn kém nên chúng cần bộ nhớ đệm và chúng không được phát hiện và không thể phát hiện quá trình tắt máy một cách đáng tin cậy và bạn không đủ khả năng để rò rỉ chúng.

0

Một đối tượng nên được xử lý bởi lớp tạo ra nó. Vì người gọi của bạn chưa tạo các mục trong bộ nhớ cache, nên họ cũng không có việc xử lý chúng.

tôi muốn chắc chắn rằng phương pháp nhà máy của bạn được đặt tên theo một cái gì đó như "Get Lớp" hơn là "Tạo Lớp" để nhấn mạnh rằng người gọi không chịu trách nhiệm cho sự sáng tạo, và do đó không cho vứt bỏ.

+0

"tác giả là chủ sở hữu" là hướng dẫn thiết kế có thể, nhưng như câu trả lời của bạn đã cho biết: không phải lúc nào cũng rõ ràng ai là người tạo (nhà máy hoặc khách hàng nhà máy?). Tốt hơn là nên viết rõ ràng và rõ ràng tài liệu này. Như câu trả lời của tôi cho thấy, bạn thậm chí có thể chuyển quyền sở hữu sau đó. –

1

Bạn có thể giải quyết vấn đề này với một nhà máy cấp và IDisposable. Ví dụ:

public class CachedObject : IDisposable { 
    private int mRefCount; 
    private CachedObject(int something) { 
    mRefCount = 1; 
    } 
    public static CachedObject CreateObject(int something) { 
    CachedObject obj = LookupInCache(something); 
    if (obj != null) Interlocked.Increment(ref obj.mRefCount); 
    else obj = new CachedObject(something); 
    return obj; 
    } 
    private static CachedObject LookupInCache(int something) { 
    CachedObject obj = null; 
    // Implement cache lookup here, don't forget to lock 
    //.. 
    return obj; 
    } 
    public void Dispose() { 
    int cnt = Interlocked.Decrement(ref mRefCount); 
    if (cnt == 0) { 
     // Remove from cache 
     // 
    } 
    } 
} 
+0

Giải pháp này có thể có một số hiệu ứng không mong muốn vì nó nghiêng khái niệm về quyền sở hữu. Mã máy khách chịu trách nhiệm cho việc vứt bỏ, nhưng nếu đối tượng có thể thay đổi được thì cũng cần lưu ý rằng có thể có các chủ sở hữu khác đang làm việc với cùng một đối tượng. –

+1

Không, nếu có thể thay đổi thì không nên lưu vào bộ nhớ cache. –

+1

Lớp này không phải là chủ đề an toàn - inc/dec của bạn không được bảo vệ nếu bảo vệ. –

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