2008-11-27 29 views
5

Đây là một nhiệm vụ tương đối phổ biến đối với tôi, và, tôi nghĩ, đối với nhiều lập trình viên .NET:
Tôi muốn sử dụng .NET ThreadPool để lập lịch trình các luồng công nhân cần xử lý một kiểu đã cho nhiệm vụ.Generic ThreadPool trong .NET

Là một bồi dưỡng, chữ ký cho phương pháp xếp hàng của ThreadPool và đại biểu liên quan của nó là:

public static bool QueueUserWorkItem (
    WaitCallback callBack, 
    Object state 
) 
public delegate void WaitCallback (Object state) 

Do đó, một chung lớp sợi nhân điển hình sẽ giống như thế:

public class Worker<T> { 
    public void schedule(T i_task) { 
     ThreadPool.QueueUserWorkItem(execute, i_task) 
    } 
    private void execute(Object o){ 
     T task = (T)o; //What happened to the type safety? 
     executeTask(task); 
    } 
    private void executeTask(T i_task){ 
     //process i_task 
    } 
} 

Lưu ý loại tham số state? Đó là Object!

Lý do thuyết phục tại sao nhóm .NET đã chọn không thực hiện phương thức QueueUserWorkItem (hoặc toàn bộ lớp ThreadPool) chung? Tôi không thể tin rằng họ chỉ bỏ qua nó.

Đây là cách tôi muốn nhìn thấy nó:

//in the ThreadPool class: 
public static bool QueueUserWorkItem<T> (
    WaitCallback<T> callBack, 
    T state 
) 
public delegate void WaitCallback<T> (T state) 

Điều này sẽ làm cho các loại an toàn giai cấp công nhân (và rất nhiều rõ ràng hơn, IMHO):

public class Worker<T> { 
    public void schedule(T i_task) { 
     ThreadPool.QueueUserWorkItem<T>(execute, i_task) 
    } 
    private void execute(T i_task){ 
     //process i_task 
    } 
} 

tôi phải mất một cái gì đó.

Trả lời

5

Có vẻ như bạn đang nói về hàng đợi công việc? (và tôi âm thanh như clippy ...)

Để ghi lại, chủ đề chuỗi chủ đề thường nên được sử dụng cho các tác phẩm ngắn. Bạn nên lý tưởng tạo chủ đề của riêng bạn cho một hàng đợi lâu. Lưu ý rằng .NET 4.0 có thể áp dụng các thư viện CCR/TPL, vì vậy chúng ta sẽ nhận được một số hàng đợi làm việc sẵn có miễn phí - nhưng không khó để viết một hàng đợi công việc luồng. Và bạn có thể làm cho nó chung chung, quá ;-p

Re câu hỏi - Tôi thích cách tiếp cận các biến bị bắt để đi qua nhà nước thành chủ đề (được họ Thread, ThreadPool, hoặc Control.Invoke):

Thread t = new Thread(() => SomeMethod(arg)); 
    t.IsBackground = true; 
    t.Name = "Worker n"; 
    t.Start(); 

Điều này cho phép bạn kiểm soát chi tiết hơn đối với sợi chỉ, không cần bão hòa ThreadPool.

+2

Tôi không hiểu đối số của bạn về việc không sử dụng nhóm luồng làm lớp 'thực thi' cơ bản của hàng đợi công việc. Đây có phải là vấn đề khi sử dụng * the *.NET ThreadPool lớp do số lượng hạn chế của chủ đề đó? IMO nó tự nhiên để giả định nhiệm vụ trong một hàng đợi công việc là ngắn. Bạn có thể vui lòng xây dựng? –

7

Vì nó tầm thường để đóng gói bất kỳ trạng thái nào bạn thích bằng cách chuyển một đại biểu ẩn danh hoặc lambda đến luồng (thông qua biến chụp), không cần cho một phiên bản chung.

Ví dụ, bạn có thể viết một hàm tiện ích:

static void QueueItem<T>(Action<T> action, T state) 
{ 
    ThreadPool.QueueUserWorkItem(delegate { action(state); }); 
} 

Nhưng nó sẽ không được terribly hữu ích, như bạn chỉ có thể sử dụng một đại biểu cho mình bất kỳ lúc nào bạn cần nhà nước trong nhiệm vụ gộp.

1

ThreadPool tồn tại từ .NET 1.1 không có Generics.

Tôi thích cách họ chọn không phá vỡ khả năng tương thích ngược :-)

+5

Tôi không nghĩ đây là một đối số hợp lệ. Chỉ cần nhìn vào tất cả các lớp container trong 1.1 đã được "nâng cấp" để sử dụng generics trong 2.0. Thêm vào đó, tôi đã không đề xuất * thay thế * phương thức Queue ... với đối tác chung chung của nó, nhưng để thêm phiên bản chung cùng với nó. –