Bir .NET uygulamasında en fazla iş parçacığı sayısı?


140

Bir C # uygulamasında oluşturabileceğiniz maksimum iş parçacığı sayısı nedir? Ve bu sınıra ulaştığınızda ne olur? Bir çeşit istisna atıldı mı?


X64 VM veya x86 VM'de çalışıyorsanız cevap değişecektir
Brian R. Bondy

Benim durumumda x86, ama başka birinin ihtiyacı olması durumunda her ikisine de cevap verebilir misiniz?

Yanıtlar:


145

Doğal bir sınır yoktur. Maksimum iş parçacığı sayısı, kullanılabilir fiziksel kaynakların miktarına göre belirlenir. Ayrıntılar için Raymond Chen'in bu makalesine bakın .

Maksimum iş parçacığı sayısının ne olduğunu sormanız gerekiyorsa, muhtemelen yanlış bir şey yapıyorsunuzdur.

[ Güncelleme : Sadece ilgi çekici: .NET Thread Pool varsayılan iş parçacığı sayısı:

  • 1023 Framework 4.0'da (32 bit ortam)
  • Framework 4.0'da 32767 (64 bit ortam)
  • Framework 3.5'te çekirdek başına 250
  • Framework 2.0'daki çekirdek başına 25

(Bu sayılar donanıma ve işletim sistemine bağlı olarak değişebilir)]


13
Bunu nasıl anladın? .NET 4.5'in ne olduğunu veya 5.0'ın ne olacağını biliyor musunuz?
goodguys_activate

3
Sayıları almak için bu kodu kullanabilirsiniz: int workerThreads; int completionPortThreads; ThreadPool.GetMaxThreads (dışarı workerThreads, dışarı completionPortThreads);
JALLRED

1
@MitchWheat Kendimi merak ediyordum, çünkü bağlantılı makale .NET'i değil düz 'ol
C.'yi tartışıyor

1
@LoukMo: bir iş parçacığı oluşturamazsanız, muhtemelen belleğiniz bitmiştir! Ben denemedim, ama bir bellek istisnası atılacak varsayıyorum ....?
Mitch Wheat

1
@Liam Bağlantının düzeltilmesi gerekiyor.
Eugene Komisarenko

26

Mitch haklı. Kaynaklara (belleğe) bağlıdır.

Raymond'un makalesi C # iş parçacıklarına değil, Windows iş parçacıklarına ayrılmış olsa da, mantık aynı şekilde uygulanır (C # iş parçacıkları Windows iş parçacıklarıyla eşlenir).

Bununla birlikte, C # 'da olduğumuz için, tamamen hassas olmak istiyorsak, "başlatılan" ve "başlatılmamış" iş parçacıkları arasında ayrım yapmamız gerekir. Sadece başlatılan iş parçacıkları aslında yığın alanı ayırır (beklediğimiz gibi). Başlatılamayan iş parçacıkları yalnızca bir iş parçacığı nesnesi için gerekli bilgileri ayırır (gerçek üyelerle ilgileniyorsanız reflektör kullanabilirsiniz).

Aslında kendiniz test edebilirsiniz, karşılaştırın:

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

ile:

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

Sayaç değerini görmek için VS'de istisna (tabii ki bellek dışı) bir kesme noktası koyun. Tabii ki çok önemli bir fark var.


9

c # konsol ile 64bit sistemde bir test yaptım, istisna 2949 iş parçacığı kullanarak bellek yetersiz, türüdür.

Yaptığım iş parçacığı havuzu kullanmamız gerektiğini anlıyorum, ancak bu cevap ana soruya cevap;)


6

Sistemin kaç iş parçacığının çalıştırılması gerektiğine karar verebilmesi için iş parçacığı havuzunu (veya iş parçacığı havuzunu kullanan zaman uyumsuz delgates) kullanıyor olmalısınız.


Cevap , sistemin karar vermesine izin vermektir.
Ian Boyd

@Ian: Seni aşağıladım çünkü aynı cevap dokuz ay önce verildi.
John Saunders

11
Bağlantı. iş parçacığı havuzu kimsenin cevabı olarak herhangi bir söz görmüyorum.
Ian Boyd

4

C # üzerinden CLR'de Jeff Richter:

"CLR'nin 2.0 sürümünde, maksimum çalışan iş parçacığı sayısı varsayılan olarak makinedeki CPU başına 25'tir ve maksimum G / Ç iş parçacığı sayısı varsayılan olarak 1000'dir. 1000 sınırı etkin bir şekilde sınırsızdır."

Bunun .NET 2.0 tabanlı olduğunu unutmayın. Bu, .NET 3.5'te değişmiş olabilir.

[Düzenle] @Mitch'in işaret ettiği gibi, bu CLR ThreadPool'a özgüdür. Doğrudan iş parçacıkları oluşturuyorsanız @Mitch ve diğerlerinin yorumlarına bakın.


.NET 3.5 hakkındaki yorumunuzda CLR 2.0 ve .NET 2.0'ı karıştırıyorsunuz.
bzlm

Bildiğim kadarıyla .NET 2.0 için SP1 (.NET 3.5'in bir parçası), iş parçacığı iş parçacığı varsayılan CPU / çekirdek için iş parçacığı havuzları için 250 olarak değiştirdi.
Michael Damatov

0

Bu kod parçasını kullanarak test edebilirsiniz :

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 bit ve 64 bit uygulama modlarına dikkat edin.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.