จำนวนเธรดสูงสุดในแอพ. NET?


143

จำนวนเธรดสูงสุดที่คุณสามารถสร้างในแอปพลิเคชัน C # คือเท่าใด และจะเกิดอะไรขึ้นเมื่อคุณมาถึงขีด จำกัด นี้? มีการโยนข้อยกเว้นบางประเภทหรือไม่?


คำตอบจะแตกต่างกันไปหากคุณใช้งานบน x64 VM หรือ x86 VM
Brian R.Bondy

ในสถานการณ์ของฉันมันคือ x86 แต่คุณสามารถให้คำตอบสำหรับทั้งสองในกรณีที่มีคนอื่นต้องการได้หรือไม่?

คำตอบ:


149

ไม่มีขีด จำกัด โดยธรรมชาติ จำนวนเธรดสูงสุดถูกกำหนดโดยจำนวนทรัพยากรทางกายภาพที่มีอยู่ ดูบทความนี้โดย Raymond Chenสำหรับข้อมูลเฉพาะ

หากคุณต้องการถามว่าจำนวนเธรดสูงสุดคือเท่าใดคุณอาจทำอะไรผิดพลาด

[ อัปเดต : ไม่สนใจ: .NET Thread Pool จำนวนเธรดเริ่มต้น:

  • 1023 ใน Framework 4.0 (สภาพแวดล้อม 32 บิต)
  • 32767 ใน Framework 4.0 (สภาพแวดล้อม 64 บิต)
  • 250 ต่อคอร์ใน Framework 3.5
  • 25 ต่อคอร์ใน Framework 2.0

(ตัวเลขเหล่านี้อาจแตกต่างกันไปขึ้นอยู่กับฮาร์ดแวร์และระบบปฏิบัติการ)]


13
คุณคิดออกได้อย่างไร? คุณรู้หรือไม่ว่า. NET 4.5 คืออะไรหรือ 5.0 จะเป็นอย่างไร?
goodguys_activate

3
คุณสามารถใช้รหัสนี้เพื่อรับจำนวน: int workerThreads; int completePortThreads; ThreadPool.GetMaxThreads (ใช้งานคนงานออก, ออก completePortThreads);
JALLRED

1
@MitchWheat ฉันสงสัยตัวเองเพราะบทความที่เชื่อมโยงไม่ได้พูดถึง. NET แต่เป็น 'ol C.
pqsk

1
@LoukMo: ถ้าคุณไม่สามารถสร้างเธรดได้แสดงว่าคุณมีหน่วยความจำหมดแล้ว! ฉันยังไม่ได้ลอง แต่สมมติว่าจะมีข้อยกเว้นความทรงจำถูกโยน .... ?
Mitch Wheat

1
@Liam ลิงค์ควรได้รับการแก้ไขแล้ว
Eugene Komisarenko

27

มิทช์พูดถูก ขึ้นอยู่กับทรัพยากร (หน่วยความจำ)

แม้ว่าบทความของ Raymond จะมีไว้สำหรับเธรดของ Windows ไม่ใช่สำหรับเธรด C # แต่ตรรกะก็ใช้เหมือนกัน (เธรด C # ถูกแมปกับเธรด Windows)

อย่างไรก็ตามในขณะที่เราอยู่ใน C # หากเราต้องการความแม่นยำอย่างสมบูรณ์เราจำเป็นต้องแยกความแตกต่างระหว่างเธรด "เริ่มต้น" และ "ยังไม่เริ่ม" เฉพาะเธรดที่เริ่มต้นเท่านั้นที่จองพื้นที่สแต็ก (ตามที่เราคาดหวัง) เธรดที่ไม่ได้เริ่มต้นจะจัดสรรข้อมูลที่จำเป็นโดยอ็อบเจ็กต์เธรดเท่านั้น (คุณสามารถใช้ตัวสะท้อนหากสนใจในสมาชิกจริง)

คุณสามารถทดสอบด้วยตัวคุณเองเปรียบเทียบ:

    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)
        {
        }
    }

กับ:

   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)
        {
        }
    }

ใส่เบรกพอยต์ในข้อยกเว้น (แน่นอนว่าหน่วยความจำไม่เพียงพอ) ใน VS เพื่อดูค่าของตัวนับ มีความแตกต่างอย่างมีนัยสำคัญแน่นอน


9

ฉันทำการทดสอบบนระบบ 64 บิตพร้อมคอนโซล c # ข้อยกเว้นคือประเภทหน่วยความจำไม่เพียงพอโดยใช้เธรด 2949

ฉันรู้ว่าเราควรใช้เธรดพูลซึ่งฉันทำ แต่คำตอบนี้ตอบสนองต่อคำถามหลัก;)


6

คุณควรใช้เธรดพูล (หรือตัวคั่นแบบ async ซึ่งจะใช้เธรดพูล) เพื่อให้ระบบสามารถตัดสินใจได้ว่าควรรันเธรดจำนวนเท่าใด


คำตอบคือปล่อยให้ระบบตัดสินใจ
Ian Boyd

@ Ian: ฉันลงคะแนนให้คุณเพราะได้รับคำตอบเดียวกันเมื่อเก้าเดือนก่อน
John Saunders

11
ลิงค์. ฉันไม่เห็นการกล่าวถึงเธรดพูลเป็นคำตอบของใครเลย
Ian Boyd

4

Jeff Richter ใน CLR ผ่าน C #:

"ด้วยเวอร์ชัน 2.0 ของ CLR จำนวนเธรดผู้ปฏิบัติงานสูงสุดจะมีค่าเริ่มต้นเป็น 25 ต่อ CPU ในเครื่องและจำนวนเธรด I / O สูงสุดจะมีค่าเริ่มต้นเป็น 1,000 ขีด จำกัด 1,000 นั้นไม่มีขีด จำกัด อย่างมีประสิทธิผล"

หมายเหตุนี่ขึ้นอยู่กับ. NET 2.0 สิ่งนี้อาจมีการเปลี่ยนแปลงใน. NET 3.5

[แก้ไข] ตามที่ @Mitch ชี้ให้เห็นสิ่งนี้เฉพาะสำหรับ CLR ThreadPool หากคุณกำลังสร้างชุดข้อความโดยตรงโปรดดูความคิดเห็นของ @Mitch และอื่น ๆ


คุณกำลังสับสน CLR 2.0 และ. NET 2.0 ในความคิดเห็นของคุณเกี่ยวกับ. NET 3.5
bzlm

เท่าที่ฉันรู้ SP1 สำหรับ. NET 2.0 (ส่วนหนึ่งของ. NET 3.5) เปลี่ยนค่าเริ่มต้นของเธรดของผู้ปฏิบัติงานเป็น 250 ต่อ CPU / คอร์สำหรับเธรดพูล
Michael Damatov

0

คุณสามารถทดสอบได้โดยใช้โค้ดสนิปนี้:

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);
   }
}

ระวังแอปพลิเคชันโหมด 32 บิตและ 64 บิต


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.