web-dev-qa-db-ja.com

.NETアプリケーションの同時スレッドの数をカウントする方法は?

Parallel.ForEachは新しいスレッドを生成し続けます 同時スレッドの数をカウントする正しい方法であるかどうかはまだ疑問です。

私が見るのは、メソッドがParallel.ForEachで同時に入力されたが完了していない反復(ループ)の数をカウントするということです。
正しい数の同時実行スレッドを伝える同時スレッド数の同義語ですか?
私は専門家ではありませんが、想像できます:

  • スレッドは再利用でき、そのアクティビティは後で継続するためにどこかでスワップされます。
  • 理論的には、ループアクティビティに関与しているスレッドは、ループの完了後にスレッドプールに保持されますが、別のスレッドには再利用されません
  • または、実験の純度を歪める可能性は何ですか?

とにかく、.NETプロセスの実行中のスレッドの量を、できれば(C#)コードで直接カウントする方法は?

更新:

したがって、 Jeppe Stig Nielsenの答え に従い、カウントに使用する場合

directThreadsCount = Process.GetCurrentProcess().Threads.Count;

出力は、リリース(threadsCount == 7)モードとデバッグ(threadsCount == 15)モードの両方で非常に似ています。

[Job 0 complete. 2 threads remaining but directThreadsCount == 7
[Job 1 complete. 1 threads remaining but directThreadsCount == 7
[Job 2 complete. 2 threads remaining but directThreadsCount == 7
[Job 4 complete. 2 threads remaining but directThreadsCount == 7
[Job 5 complete. 2 threads remaining but directThreadsCount == 7
[Job 3 complete. 2 threads remaining but directThreadsCount == 7
[Job 6 complete. 2 threads remaining but directThreadsCount == 7
[Job 9 complete. 2 threads remaining but directThreadsCount == 7
[Job 7 complete. 1 threads remaining but directThreadsCount == 7
[Job 8 complete. 0 threads remaining but directThreadsCount == 7
FINISHED

つまり、スレッドの数が減ることはなく、 上記のメソッド が正しくないことを示しています。 System.Diagnostics.ProcessThread"Class name is not valid at this point"を返します

私の結論は正しいですか なぜProcessThreadを使用できないのか

C#コンソールアプリケーションの使用コード:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Edit4Posting
{
public class Node
{

  public Node Previous { get; private set; }
  public Node(Node previous)
  {
    Previous = previous;
    }
  }
  public class Edit4Posting
  {

    public static void Main(string[] args)
    {
      int concurrentThreads = 0;
      int directThreadsCount = 0;
      int diagThreadCount = 0;

      var jobs = Enumerable.Range(0, 10);
      Parallel.ForEach(jobs, delegate(int jobNr)
      {
        int threadsRemaining = Interlocked.Increment(ref concurrentThreads);

        int heavyness = jobNr % 9;

        //Give the processor and the garbage collector something to do...
        List<Node> nodes = new List<Node>();
        Node current = null;
        //for (int y = 0; y < 1024 * 1024 * heavyness; y++)
        for (int y = 0; y < 1024 * 24 * heavyness; y++)
        {
          current = new Node(current);
          nodes.Add(current);
        }
        //*******************************
        //uncommenting next line gives: "Class name is not valid at this point"
        //diagThreadCount=System.Diagnostics.ProcessThread
        directThreadsCount = Process.GetCurrentProcess().Threads.Count;
        //*******************************
        threadsRemaining = Interlocked.Decrement(ref concurrentThreads);
        Console.WriteLine(
           "[Job {0} complete. {1} threads remaining but directThreadsCount == {2}",
            jobNr, threadsRemaining, directThreadsCount);
      });
      Console.WriteLine("FINISHED");
      Console.ReadLine();
    }
  }
}
18
Fulproof

スレッドにはさまざまな種類があると思います。実行中のアプリケーションのオペレーティングシステムのスレッドは、次のものでカウントできます。

int number = Process.GetCurrentProcess().Threads.Count;

System.Diagnostics.ProcessThreadインスタンス。 「マネージスレッド」のような別の種類のスレッドをカウントする必要があるかもしれないので、私の答えがあなたの求めるものかどうかはわかりません。

46

私は専門家ではありませんが、スレッドがどこかで交換されている間にスレッドを再利用できると想像できます。

いいえ-いくつかのvery特定の場合を除き(ほとんど確実に心配する必要はありません)、スレッドはリエントラントに使用されません。スレッドは、別の反復(または他のタスク)を実行するために再利用されますafter現在の反復が完了しましたが、他の何かをするように要求されませんwhileあなたのコードが走っています。

したがって、基本的には現在のアプローチは妥当です。

とにかく、.NETで実行中のスレッドの量を直接カウントする方法は?

Perfmonを見ると、グラフが表示されます。 (プロセスが制御下にある場合は、プロセスを開始するのが最も簡単ですが、入力を待ってからperfmonを開き、「プロセス」オプションからカウンターを追加し、追加するカウンターとして「スレッドカウント」を選択し、制限しますドロップダウンから目的のプロセスに追加します。[OK]をクリックして、プロセスを動作させます。)

編集:アップデートに回答するには:

つまり、スレッドの数が減ることはなく、上記の方法が間違っていることを示しています。

いいえ、コードをアクティブに実行しているスレッドの数が減っていることだけが示されていますが、スレッドは保持されています。これは、スレッドプールにとってまったく自然なことです。

なぜProcessThreadを使用できないのですか?

あなたは単にそれを不適切に使用しています。 Jeppeによると、システムはProcessThreadのインスタンスをカウントであるのに対し、コードはクラスを変数に割り当てようとします。

diagThreadCount=System.Diagnostics.ProcessThread

それは単に無効なコードです。エラーメッセージは、コンパイラがそれが型の名前であることを認識していることを示していますが、変数に型名を割り当てることはできません。

11
Jon Skeet