現在実行中のすべてのタスクのリストを取得しようとしています。.net 4.0 タスク API はそのような機能を提供しますか? それとも、タスクを別のコレクションに明示的に保存することが唯一の選択肢ですか?
5 に答える
TaskScheduler.GetScheduledTasksメソッドが必要だと思いますが、
- 保護されている
- MSDNは、デバッグにのみ使用する必要があると述べています
- 私の知る限り、このメソッドは ThreadPoolTaskScheduler によってのみ実装されており、SynchronizationContextTaskScheduler は常に null を返します。
したがって、目標を達成するには、独自の TaskSchedulerを実装する必要があると思います。
タスクを作成すると、既定では、タスクはスレッド プールスレッドで実行されるようにスケジュールされます。したがって、 ThreadPool.GetMaxThreadsおよびThreadPool.GetAvailableThreadsメソッドを使用して、実行中のタスクの数を取得できます。
private static int GetWorkingThreads() {
int maxThreads;
int completionPortThreads;
ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
int availableThreads;
ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
return maxThreads - availableThreads;
}
実行中のタスクのリストを見つけたいのはなぜですか?デバッグとは別に、この情報を使用する必要はありません。いずれにせよ、実行がスケジュールされているタスクのリストと実際に実行されているタスクには違いがあります。
Rustedが書いているように、TaskScheduler.GetScheduledTasksメソッドからスケジュールされたタスクの数を取得できます。このメソッドは抽象的であるため、すべてのTaskSchedulersで実装する必要があります。
実際に実行されるタスクの数は、TaskSchedulerの実装によって異なります。デフォルトのタスクスケジューラはスレッドプールを使用します。この場合、ThreadPool.GetAvailableThreadsとThreadPool.GetMaxThreadsをチェックして、実行中のタスクの数を概算する必要があります。
デフォルトのTaskSchedulerを使用している場合でも、実行中のタスクの実際のリストはありません。スケジューラーは基本的にタスクをThreadPoolに割り当て、実際の実行をプールに任せます(実際には、Task.ExecuteEntryプライベートメソッドを呼び出します)。実行中のタスクのリストを保持する必要はありません。
デバッグ目的で実行中のタスク情報が必要な場合は、TPLのWindowsイベントのイベントトレースを利用できます。残念ながら、タスク開始イベントとタスク終了イベントは文書化されていません。dotPeekでTask.ExecuteEntryの定義を参照しているときにそれらを見つけました。
TPLイベントを調査している記事を1つ見つけましたが、それが問題の価値があるかどうかはわかりません。独自のデバッガーを作成していない限り、問題が多すぎるようです。
実行中のタスクのリストにアクセスする必要がある場合は、独自のTaskSchedulerを作成し、TryExecuteとTryExecuteInternalをオーバーライドして、各タスクの実行をインターセプトし、各タスクをリストに配置する必要があります。ただし、これにはコストがかかる可能性があり、継続を使用せずに完了したタスクをリストから削除するには、定期的にクリーンアップを実行する必要があります(リスト自体に含まれることになります)。
MSDN に良い記事がありますhttp://msdn.microsoft.com/en-us/library/ms997649.aspx 必要なものはすべて非常によく説明されています。
編集:おそらくこれが役立ちます:
using System;
using System.Diagnostics;
class MainClass
{
public static void Main()
{
Process[] allProcs = Process.GetProcesses();
foreach(Process proc in allProcs)
{
ProcessThreadCollection myThreads = proc.Threads;
Console.WriteLine("process: {0}, id: {1}", proc.ProcessName, proc.Id);
foreach(ProcessThread pt in myThreads)
{
Console.WriteLine(" thread: {0}", pt.Id);
Console.WriteLine(" started: {0}", pt.StartTime.ToString());
Console.WriteLine(" CPU time: {0}", pt.TotalProcessorTime);
Console.WriteLine(" priority: {0}", pt.BasePriority);
Console.WriteLine(" thread state: {0}", pt.ThreadState.ToString());
}
}
}
}