Jumlah maksimum utas dalam aplikasi .NET?

143

Berapa jumlah maksimum utas yang dapat Anda buat dalam aplikasi C #? Dan apa yang terjadi jika Anda mencapai batas ini? Apakah pengecualian dari beberapa jenis dilemparkan?

John Saunders
sumber
Jawabannya akan berbeda jika Anda menjalankan VM x64 atau VM x86
Brian R. Bondy
Dalam situasi saya, ini x86, tetapi dapatkah Anda memberikan jawaban untuk keduanya jika orang lain membutuhkannya?

Jawaban:

149

Tidak ada batasan yang melekat. Jumlah maksimum utas ditentukan oleh jumlah sumber daya fisik yang tersedia. Lihat artikel ini oleh Raymond Chen untuk spesifikasinya.

Jika Anda perlu bertanya berapa jumlah utas maksimum, Anda mungkin melakukan sesuatu yang salah.

[ Pembaruan : Hanya karena minat: Jumlah utas .NET Thread Pool default:

  • 1023 di Framework 4.0 (lingkungan 32-bit)
  • 32767 di Framework 4.0 (lingkungan 64-bit)
  • 250 per inti dalam Kerangka 3.5
  • 25 per inti dalam Framework 2.0

(Angka-angka ini dapat bervariasi tergantung pada perangkat keras dan OS)]

Mitch Wheat
sumber
13
Bagaimana Anda mengetahui hal ini? Apakah Anda tahu apa itu .NET 4.5, atau apa yang akan menjadi 5.0?
goodguys_activate
3
Anda bisa menggunakan kode ini untuk mendapatkan hitungan: int workerThreads; int completePortThreads; ThreadPool.GetMaxThreads (keluar workerThreads, keluar penyelesaianPortThreads);
DIJALLRED
1
@MitchWheat Saya bertanya-tanya pada diri saya sendiri, karena artikel yang ditautkan tidak membahas .NET, tetapi biasa 'ol C.
pqsk
1
@LoukMo: jika Anda tidak dapat membuat utas, maka Anda mungkin kehabisan memori! Saya belum mencobanya, tetapi saya berasumsi pengecualian memori akan dibuang ....?
Mitch Wheat
1
@ Liam Tautan sekarang sudah diperbaiki.
Eugene Komisarenko
27

Mitch benar. Itu tergantung pada sumber daya (memori).

Meskipun artikel Raymond didedikasikan untuk utas Windows, bukan utas C #, logikanya berlaku sama (utas C # dipetakan ke utas Windows).

Namun, karena kita berada di C #, jika kita ingin benar-benar tepat, kita perlu membedakan antara utas "mulai" dan "tidak dimulai". Hanya utas awal yang benar-benar memesan ruang tumpukan (seperti yang bisa kita harapkan). Utas yang tidak dimulai hanya mengalokasikan informasi yang diperlukan oleh objek utas (Anda dapat menggunakan reflektor jika tertarik dengan anggota sebenarnya).

Anda sebenarnya bisa mengujinya sendiri, bandingkan:

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

dengan:

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

Letakkan breakpoint di pengecualian (kehabisan memori, tentu saja) di VS untuk melihat nilai penghitung. Ada perbedaan yang sangat signifikan tentunya.

antonio
sumber
9

saya melakukan tes pada sistem 64bit dengan konsol c #, pengecualiannya adalah tipe dari memori, menggunakan 2949 utas.

Saya menyadari kita harus menggunakan kumpulan threading, yang saya lakukan, tetapi jawaban ini adalah sebagai tanggapan atas pertanyaan utama;)

MadApples
sumber
6

Anda harus menggunakan kumpulan utas (atau pemisah asinkron, yang pada gilirannya menggunakan kumpulan utas) sehingga sistem dapat memutuskan berapa banyak utas yang harus dijalankan.

Ian Boyd
sumber
Jawabannya adalah biarkan sistem memutuskan.
Ian Boyd
@Ian: Saya tidak menyukai Anda karena jawaban yang sama diberikan sembilan bulan sebelumnya.
John Saunders
11
Tautan. Saya tidak melihat ada penyebutan kumpulan benang sebagai jawaban siapa pun.
Ian Boyd
4

Jeff Richter di CLR melalui C #:

"Dengan CLR versi 2.0, jumlah maksimum utas pekerja default ke 25 per CPU di mesin dan jumlah maksimum utas I / O default ke 1000. Batas 1000 secara efektif tidak ada batasan sama sekali."

Perhatikan bahwa ini didasarkan pada .NET 2.0. Ini mungkin telah berubah di .NET 3.5.

[Sunting] Seperti yang ditunjukkan @Mitch, ini khusus untuk CLR ThreadPool. Jika Anda membuat utas secara langsung, lihat komentar @Mitch dan lainnya.

Abu
sumber
Anda bingung dengan CLR 2.0 dan .NET 2.0 dalam komentar Anda tentang .NET 3.5.
bzlm
Sejauh yang saya tahu, SP1 untuk .NET 2.0 (bagian dari .NET 3.5) mengubah default utas pekerja menjadi 250 per CPU / inti untuk kumpulan utas.
Michael Damatov
0

Anda dapat mengujinya dengan menggunakan kode yang dipotong ini:

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

Waspadalah terhadap mode aplikasi 32-bit dan 64-bit.

Yousha Aleayoub
sumber