27

Parallel.ForEachを読んでも新しいスレッドが生成され続けますが、それが同時実行スレッドの数をカウントする正しい方法であるかどうかはまだ疑問です。

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

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

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

アップデート:

したがって、 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();
    }
  }
}
4

2 に答える 2

13

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

いいえ -非常に特殊なケース (ほぼ確実に心配する必要はない) を除いて、スレッドは再入可能に使用されません。スレッドは、現在の反復が完了した、別の反復 (または他のタスク) を実行するために再利用されますが、コードの実行中に他のことを行うように求められることはありません。

基本的に、あなたの現在のアプローチは合理的です。

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

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

編集:更新に答えるには:

つまり、スレッドの数が減少することはありません。これは、上記の方法が正しくないことを示しています。

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

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

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

diagThreadCount=System.Diagnostics.ProcessThread

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

于 2013-03-13T09:22:15.753 に答える