(Đăng ngày 16/11/2007) Nếu ứng dụng của bạn có nhiều luồng mà phần lớn thời gian của chúng bị chặn trên Xử lý Chờ, bạn có thể giảm gánh nặng tài nguyên thông qua gộp luồng. Một nhóm chủ đề tiết kiệm bằng cách kết hợp nhiều Tay cầm Chờ vào một vài chủ đề.

Để sử dụng nhóm luồng, bạn đăng ký một Xử lý Chờ cùng với một đại biểu để được thực thi khi Xử lý Chờ được báo hiệu. Điều này được thực hiện bằng cách gọi ThreadPool.RegisterWaitForSingleObject, chẳng hạn như trong ví dụ này:

class Test {
static ManualResetEvent starter = new ManualResetEvent (false);

public static void Main () {
ThreadPool.RegisterWaitForSingleObject (starter, Go, “hello”, -1, true);
Thread.Sleep (5000);
Console.WriteLine (“Công nhân báo hiệu …”);
starter.Set ();
Console.ReadLine ();
}

public static void Go (object data, bool timedOut) {
Console.WriteLine (“Started” + data);
// Thực hiện tác vụ …
}
}

 

(Chậm trễ 5 giây)
Nhân viên báo hiệu … Đã
bắt đầu xin chào

Ngoài Xử lý Chờ và ủy quyền, RegisterWaitForSingleObject chấp nhận một đối tượng “hộp đen” mà nó chuyển đến phương thức ủy quyền của bạn (giống như với ParameterizedThreadStart), cũng như thời gian chờ tính bằng mili giây (-1 nghĩa là không có thời gian chờ) và cờ boolean cho biết nếu yêu cầu là một lần thay vì lặp lại.

Tất cả các luồng tổng hợp là các luồng nền, nghĩa là chúng tự động kết thúc khi (các) luồng nền trước của ứng dụng kết thúc. Tuy nhiên, nếu một người muốn đợi cho đến khi bất kỳ công việc quan trọng nào chạy trên các chuỗi được gộp chung hoàn tất trước khi thoát ứng dụng, thì việc gọi Tham gia trên các chuỗi sẽ không phải là một tùy chọn, vì các chuỗi gộp không bao giờ kết thúc! Ý tưởng là chúng được tái chế thay vào đó và chỉ kết thúc khi quy trình mẹ kết thúc. Vì vậy, để biết khi nào một công việc chạy trên một luồng tổng hợp đã kết thúc, người ta phải báo hiệu – ví dụ, bằng một Xử lý Chờ khác.

Gọi Abort trên một chuỗi tổng hợp là Bad Idea. Các luồng cần được tái chế cho vòng đời của miền ứng dụng.

Bạn cũng có thể sử dụng nhóm luồng mà không có Xử lý Chờ bằng cách gọi phương thức QueueUserWorkItem – chỉ định một đại biểu để thực thi ngay lập tức. Sau đó, bạn không nhận được việc lưu các chủ đề chia sẻ giữa nhiều công việc, nhưng nhận được một lợi ích khác: nhóm chủ đề giữ một nắp về tổng số chủ đề (theo mặc định là 25), tự động sắp xếp các nhiệm vụ khi số công việc vượt quá . Nó giống như một hàng đợi nhà sản xuất-người tiêu dùng trên toàn ứng dụng với 25 người tiêu dùng! Trong ví dụ sau, 100 công việc được xếp hàng vào nhóm luồng, trong đó 25 công việc thực thi tại một thời điểm. Sau đó, chuỗi chính sẽ đợi cho đến khi tất cả chúng hoàn tất bằng cách sử dụng Wait and Pulse:

class Test {
static object workerLocker = new object ();
static int runningWorkers = 100;

public static void Main () {
for (int i = 0; i <runningWorkers; i ++) {
ThreadPool.QueueUserWorkItem (Go, i);
}
Console.WriteLine (“Đang đợi luồng hoàn thành …”);
lock (workerLocker) {
while (runningWorkers> 0) Monitor.Wait (workerLocker);
}
Console.WriteLine (“Hoàn thành!”);
Console.ReadLine ();
}

public static void Go (object instance) {
Console.WriteLine (“Started:” + instance);
Thread.Sleep (1000);
Console.WriteLine (“Đã kết thúc:” + thể hiện);
lock (workerLocker) {runningWorkers–
; Monitor.Pulse (workerLocker);
}
}
}

Để chuyển nhiều hơn một đối tượng duy nhất đến phương thức đích, người ta có thể xác định một đối tượng tùy chỉnh với tất cả các thuộc tính bắt buộc hoặc gọi thông qua một phương thức không phải là một. Ví dụ: nếu phương thức Go chấp nhận hai tham số số nguyên, nó có thể được bắt đầu như sau:

ThreadPool.QueueUserWorkItem (ủy nhiệm (đối tượng notUsed) {Go (23,34);});

Một cách khác vào nhóm luồng là thông qua các đại biểu không đồng bộ.

(Sưu tầm)

0981578920
icons8-exercise-96