2011-10-21 14 views
11

Tôi có một thư viện rất cũ nhưng rất lớn mà tôi đang xem xét chuyển đổi sang thư viện lớp C#. Thư viện hiện có sử dụng rất nhiều biến toàn cầu được lưu trữ trong TLS. C# không có khái niệm thực sự về các biến toàn cục, nhưng một cách giải quyết khác là sử dụng một lớp tĩnh gọi là GlobalVar và đặt chúng trong lớp này để chúng có thể được truy cập thông qua GlobalVar.xxxxxxLưu trữ cục bộ chủ đề Đối với thư viện lớp C#

Tuy nhiên, suy nghĩ của tôi là tất cả các mã hiện có đang được chuyển đổi thành lớp GlobalVar sẽ là một lớp toàn cầu bình thường và không phải trên mỗi lưu trữ luồng. Có cách nào để nhận được các hình cầu này trên mỗi luồng không? tức là tương đương với __declspec (luồng) tĩnh trong C# là gì?

Tôi nên thêm vào thời điểm này là tôi ghét các biến toàn cầu. Tôi nghĩ rằng chúng thường là kết quả của thiết kế kém. Tuy nhiên, do hạn chế thời gian chặt chẽ, giai đoạn một là chuyển đổi thư viện thành C# với tối thiểu fuss và sau đó giai đoạn 2 sẽ được thiết kế lại chúng đúng cách.

Trả lời

14

Có lớp ThreadLocal (được giới thiệu trong 4.0) và ThreadStaticAttribute.

Chỉ có thể sử dụng ThreadStaticAttribute trên các trường static. Lớp ThreadLocal có thể được sử dụng trên các trường "bình thường" nhưng nó chậm hơn.

Hãy lưu ý rằng nếu bạn không kiểm soát chuỗi bạn đang truy cập (ví dụ: bạn là trang ASP.NET và bạn bắt đầu theo chuỗi "được sử dụng ngẫu nhiên" hoặc bạn là chủ đề của ThreadPool), sau đó biến "thread-static" (nói chung, không phải thuộc tính) sẽ được khởi tạo trước với các giá trị cũ của chuỗi trước đó. (xem ví dụ A tale of two techniques: The [ThreadStatic] Attribute and System.Web.HttpContext.Current.Items)

Tôi đã quên, có Thread.AllocateDataSlot có mục tiêu "tương tự" so với các mục tiêu khác.

+0

Hehe, bạn dường như nhấn mạnh vào việc dạy chúng tôi tiếng Ý :-) –

+0

@xanatos 'ThreadStaticAttribute chỉ có thể được sử dụng trên các trường tĩnh' không phải lúc nào cũng đúng. Mọi người có thể muốn khai báo một biến cho mỗi thread-per-instance –

+0

Ý của tôi không phải là tuyệt vời nhưng đùa ngoài, rất cám ơn sự giúp đỡ. Mặc dù tôi hơi lo ngại về đoạn cuối cùng cần làm với việc sử dụng ThreadPool. Tôi không nghĩ rằng đây sẽ là một vấn đề lúc đầu nhưng nó là cái gì đó có thể cần xem xét trong tương lai. – Jonnster

3

Bạn có thể sử dụng thuộc tính [ThreadStatic] hoặc trong .Net 4 bằng cách sử dụng lớp ThreadLocal.

[ThreadStatic]  
private static string MyThreadGlobal; 

private ThreadLocal<string> MyThreadGlobal = new ThreadLocal<string>(); 

Còn có lớp CallContext nhưng các phương pháp tiếp cận khác có thể được ưu tiên.

3

Giả sử bạn sẽ sử dụng .NET 4.0, bạn có thể có một static ThreadLocal<ThreadLocalData> nơi lớp ThreadLocalData bạn có tất cả các biến của bạn như tài sản:

class ThreadLocalData 
{ 
    public int GlobalInt { get; set; } 
    public string GlobalString { get; set; } 
} 

class Global 
{ 
    static ThreadLocal<ThreadLocalData> _ThreadLocal = 
     new ThreadLocal<ThreadLocalData>(() => new ThreadLocalData()); 

    public static ThreadLocalData ThreadLocal 
    { 
     get { return _ThreadLocal.Value; } 
    } 
} 

Sau đó, bạn sẽ truy cập vào các tính chất như thế này:

int i = Global.ThreadLocal.GlobalInt; 

Bạn có thể thêm bất kỳ biến toàn cầu nào không phải là chuỗi địa phương làm thuộc tính bình thường của lớp Global.

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