2013-03-14 19 views
21

Tôi có một máy chủ HTTP mà tôi đang viết bằng cách sử dụng trình nghe HTTP và tôi muốn khai báo một số biến nhất định khi có thể truy cập từ bất kỳ đâu trong chuỗi.Đặt một biến toàn cầu trong một luồng - C#

  • Lớp máy chủ web của tôi được dựa trên nền tảng, vì vậy tôi không thể sử dụng biến tĩnh.
  • Tôi có thể sử dụng biến mẫu vì tất cả mã đều nằm trong một lớp, nhưng ... Tôi không biết.

Tôi đã nghĩ đến việc sử dụng từ điển: Dictionary</*[type of Thread ID here]*/,ThreadData>, nhưng tôi lo ngại có thể có vấn đề về luồng. ThreadData sẽ có lẽ là một phiên bản lớp, nhưng tôi có thể sử dụng cấu trúc, tùy thuộc vào đó sẽ hiệu quả hơn.

  • Nếu tôi sẽ chìa khóa từ điển cho các ID chủ đề và chương trình nó để một thread sẽ chỉ yêu cầu nhập riêng của mình trong từ điển, sẽ có bất kỳ vấn đề chủ đề liên quan đến khi truy cập vào từ điển?
  • Mỗi chuỗi sẽ thêm mục nhập của riêng nó. Tôi có phải khóa từ điển trong khi thêm các mục mới không? Nếu vậy, tôi có thể sử dụng một đối tượng khóa riêng biệt để cho phép các luồng truy cập dữ liệu của riêng chúng trong thời gian chờ đợi không?

Có lợi thế nào khi sử dụng từ điển đồng thời không? Có cách nào khác an toàn hơn không?

Tôi hiện đang sử dụng ThreadPool.QueueUserWorkItem. Tôi không biết chắc chắn rằng điều này sử dụng một chủ đề mới cho mỗi mục. Nếu không thì tôi cũng có thể đưa nó vào ngữ cảnh.

Cập nhật: Theo ThreadPool class - MSDN, nó sẽ sử dụng lại các chuỗi. Và nó không xóa dữ liệu luồng.

Khi nhóm chủ đề sử dụng lại chuỗi, nó không xóa dữ liệu trong lưu trữ cục bộ luồng hoặc trong trường được đánh dấu bằng thuộc tính ThreadStaticAttribute. Do đó, khi một phương thức kiểm tra lưu trữ cục bộ luồng hoặc các trường được đánh dấu bằng thuộc tính ThreadStaticAttribute, các giá trị mà nó tìm thấy có thể bị bỏ sót từ việc sử dụng luồng thread thread trước đó.

+0

Các bạn đã thử subclassing [BackgroundWorker] (http://msdn.microsoft.com/en- lớp us/library/system.componentmodel.backgroundworker.aspx)? – Romoku

+0

Bởi vì bạn có một điểm vào riêng biệt cho các chuỗi công nhân của bạn và bạn tự viết logic công nhân, nó không phải là một vấn đề để bạn xóa sạch dữ liệu luồng cũ. – Gene

Trả lời

27

Một giải pháp sẽ được sử dụng một công trường tĩnh, với thuộc tính ThreadStatic:

[ThreadStatic] 
public static int ThreadSpecificStaticValue; 

Một lĩnh vực tĩnh được đánh dấu bằng ThreadStaticAttribute không được chia sẻ giữa đề. Mỗi chuỗi thực hiện có một trường hợp riêng biệt của trường, và độc lập đặt và nhận các giá trị cho trường đó. Nếu trường là được truy cập trên một chuỗi khác, trường đó sẽ chứa một giá trị khác.

+0

Gọn gàng. Không biết điều đó. – Gene

+0

Cũng không I. Ước gì tôi có thể +2! –

+0

Vậy sự khác nhau giữa phương pháp này và câu trả lời của Gene là gì? Cả hai dường như hoàn thành cùng một điều. Tôi đoán phương pháp của Gene có thể được truy cập từ bất cứ đâu trong Thread, trong khi phương thức này tuân theo các quy ước truy cập thông thường. Cái này dễ hơn. +1 cho cả hai bạn :) –

0

Nếu máy chủ web của bạn là ví dụ, tại sao không giữ tất cả dữ liệu bắt buộc trong đó? Nếu mỗi trường hợp bị khóa vào một chuỗi nhất định, sẽ không có vấn đề gì.

+0

Không, mỗi yêu cầu của khách hàng đều có chủ đề riêng. –

+0

@ArlenBeiler Máy của bạn có bao nhiêu lõi? Luồng mọi yêu cầu sẽ khá tối ưu. Nó sẽ là tốt hơn để viết một bộ lập lịch yêu cầu sẽ phân phối công việc trên một số chủ đề. – Romoku

+0

Xin lỗi, nó sử dụng 'ThreadPool.QueueUserWorkItem'. Lỗi của tôi. –

5

Bạn có thể sử dụng được xây dựng trong cơ chế lưu trữ của lớp chủ đề: sản lượng

public class Program 
{ 
    private static LocalDataStoreSlot _Slot = Thread.AllocateNamedDataSlot("webserver.data"); 

    public static void Main(string[] args) 
    { 
    var threads = new List<Thread>(); 

    for (int i = 0; i < 5; i++) 
    { 
     var thread = new Thread(DoWork); 
     threads.Add(thread); 
     thread.Start(i); 
    } 

    foreach (var thread in threads) thread.Join(); 
    } 

    private static void DoWork(object data) 
    { 
    // initially set the context of the thread 
    Thread.SetData(_Slot, data); 

    // somewhere else, access the context again 
    Console.WriteLine("Thread ID {0}: {1}", Thread.CurrentThread.ManagedThreadId, Thread.GetData(_Slot)); 
    } 

} 

mẫu:

enter image description here

Điều đó sẽ làm việc với các chủ đề sinh ra bởi các hồ bơi thread là tốt.

0

Tại sao bạn muốn để tạo ra một HTTP Server, Sử dụng SignalR, trông câu trả lời lập dị nhưng suy nghĩ về nó