Số lượng chủ đề tối đa trong một ứng dụng .NET?


140

Số lượng chủ đề tối đa bạn có thể tạo trong ứng dụng C # là bao nhiêu? Và điều gì xảy ra khi bạn đạt đến giới hạn này? Là một ngoại lệ của một số loại ném?


Câu trả lời sẽ khác nếu bạn đang chạy trên x64 VM hoặc x86 VM
Brian R. Bondy

Trong tình huống của tôi, đó là x86, nhưng bạn có thể cung cấp câu trả lời cho cả hai trong trường hợp người khác cần nó không?

Câu trả lời:


145

Không có giới hạn vốn có. Số lượng chủ đề tối đa được xác định bởi số lượng tài nguyên vật lý có sẵn. Xem bài viết này của Raymond Chen để biết chi tiết.

Nếu bạn cần hỏi số lượng chủ đề tối đa là bao nhiêu thì có lẽ bạn đang làm sai.

[ Cập nhật : Chỉ cần quan tâm: .NET Thread Pool số lượng mặc định của chuỗi:

  • 1023 trong Khung 4.0 (môi trường 32 bit)
  • 32767 trong Khung 4.0 (môi trường 64 bit)
  • 250 mỗi lõi trong Khung 3.5
  • 25 mỗi lõi trong Khung 2.0

(Những con số này có thể thay đổi tùy theo phần cứng và HĐH)]


13
Làm thế nào bạn tìm ra điều này? Bạn có biết .NET 4.5 là gì, hay 5.0 sẽ là gì không?
goodguys_activate

3
Bạn có thể sử dụng mã này để lấy số đếm: int workerThreads; int xongPortThreads; ThreadPool.GetMaxThreads (out workerThreads, out xongPortThreads);
JALLRED

1
@MitchWheat Tôi đã tự hỏi bản thân mình, vì bài viết được liên kết không thảo luận về .NET, nhưng đơn giản là 'ol C.
pqsk

1
@LoukMo: nếu bạn không thể tạo một chủ đề, thì có lẽ bạn đã hết bộ nhớ! Tôi đã không thử nó, nhưng tôi cho rằng một ngoại lệ bộ nhớ sẽ bị ném ....?
Mitch Wheat

1
@Liam Liên kết nên được sửa chữa.
Eugene Komisarenko

26

Mitch nói đúng. Nó phụ thuộc vào tài nguyên (bộ nhớ).

Mặc dù bài viết của Raymond dành riêng cho các luồng của Windows, không dành cho các luồng C #, nhưng logic này cũng áp dụng tương tự (các luồng C # được ánh xạ tới các luồng của Windows).

Tuy nhiên, như chúng ta đang ở trong C #, nếu chúng ta muốn hoàn toàn chính xác, chúng ta cần phân biệt giữa các luồng "bắt đầu" và "không bắt đầu". Chỉ bắt đầu chủ đề thực sự dự trữ không gian ngăn xếp (như chúng ta có thể mong đợi). Các luồng không bắt đầu chỉ phân bổ thông tin theo yêu cầu của một đối tượng luồng (bạn có thể sử dụng phản xạ nếu quan tâm đến các thành viên thực tế).

Bạn thực sự có thể tự kiểm tra nó, so sánh:

    static void DummyCall()
    {
        Thread.Sleep(1000000000);
    }

    static void Main(string[] args)
    {
        int count = 0;
        var threadList = new List<Thread>();
        try
        {
            while (true)
            {
                Thread newThread = new Thread(new ThreadStart(DummyCall), 1024);
                newThread.Start();
                threadList.Add(newThread);
                count++;
            }
        }
        catch (Exception ex)
        {
        }
    }

với:

   static void DummyCall()
    {
        Thread.Sleep(1000000000);
    }

    static void Main(string[] args)
    {
        int count = 0;
        var threadList = new List<Thread>();
        try
        {
            while (true)
            {
                Thread newThread = new Thread(new ThreadStart(DummyCall), 1024);
                threadList.Add(newThread);
                count++;
            }
        }
        catch (Exception ex)
        {
        }
    }

Đặt một điểm dừng trong ngoại lệ (tất nhiên là hết bộ nhớ) trong VS để xem giá trị của bộ đếm. Có một sự khác biệt rất đáng kể, tất nhiên.


9

tôi đã thực hiện một thử nghiệm trên hệ thống 64 bit với bảng điều khiển c #, ngoại lệ là loại hết bộ nhớ, sử dụng 2949 luồng.

Tôi nhận ra rằng chúng ta nên sử dụng nhóm luồng, điều mà tôi làm, nhưng câu trả lời này là để trả lời cho câu hỏi chính;)


6

Bạn nên sử dụng nhóm luồng (hoặc async delgates, lần lượt sử dụng nhóm luồng) để hệ thống có thể quyết định số lượng luồng sẽ chạy.


Câu trả lời để cho hệ thống quyết định.
Ian Boyd

@Ian: Tôi đánh giá thấp bạn vì cùng một câu trả lời đã được đưa ra chín tháng trước.
John Saunders

11
Liên kết. tôi không thấy bất kỳ đề cập đến nhóm chủ đề như câu trả lời của bất cứ ai.
Ian Boyd

4

Jeff Richter trong CLR thông qua C #:

"Với phiên bản 2.0 của CLR, số lượng luồng công nhân tối đa mặc định là 25 trên mỗi CPU trong máy và số lượng luồng I / O tối đa mặc định là 1000. Giới hạn 1000 hoàn toàn không có giới hạn."

Lưu ý điều này dựa trên .NET 2.0. Điều này có thể đã thay đổi trong .NET 3.5.

[Chỉnh sửa] Như @Mitch đã chỉ ra, điều này là dành riêng cho CLR ThreadPool. Nếu bạn đang tạo chủ đề trực tiếp, hãy xem @Mitch và những người khác nhận xét.


Bạn đang nhầm lẫn CLR 2.0 và .NET 2.0 trong nhận xét của bạn về .NET 3.5.
bzlm

Theo như tôi biết thì SP1 cho .NET 2.0 (một phần của .NET 3.5) đã thay đổi các luồng công nhân mặc định thành 250 trên mỗi CPU / lõi cho nhóm luồng.
Michael Damatov

0

Bạn có thể kiểm tra nó bằng cách sử dụng mã snipped này:

private static void Main(string[] args)
{
   int threadCount = 0;
   try
   {
      for (int i = 0; i < int.MaxValue; i ++)
      {
         new Thread(() => Thread.Sleep(Timeout.Infinite)).Start();
         threadCount ++;
      }
   }
   catch
   {
      Console.WriteLine(threadCount);
      Console.ReadKey(true);
   }
}

Cảnh giác với chế độ ứng dụng 32 bit và 64 bit.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.