こんにちは。

現在C#勉強中なのですが、Taskクラスを使ってスレッドプログラムを書いています。  
Taskクラスでスレッドを大量に作って、タスクマネージャーでハンドル数を見ているのですが、スレッドが終了した後も増えっぱなしで減りません。以下がそのコードです。

```

        static void Main(string[] args)
        {
            var tasks = new List<Task<int>>();
    
            Console.WriteLine("Start");
            Console.ReadLine();//The number of handle is 180
    
            // Define a delegate that prints and returns the system tick count
            Func<object, int> action = (object obj) =>
            {
                int i = (int)obj;
    
                // Make each thread sleep a different time in order to return a different tick count
                Thread.Sleep(i % 100);
    
                Console.WriteLine("{0}", i);
                return i;
            };
    
            // Construct started tasks
            for (int i = 0; i < 5000; i++)
            {
                int index = i;
                tasks.Add(Task<int>.Factory.StartNew(action, index));
            }
    
            Console.WriteLine("Add end");
            Console.ReadLine(); //The number of handle is 312
    
            // Wait for all the tasks to finish.
            Task.WaitAll(tasks.ToArray());
    
            // We should never get to this point
            Console.WriteLine("WaitAll() has not thrown exceptions. THIS WAS NOT EXPECTED.");
    
            Console.WriteLine("Test END");
            Console.ReadLine(); //The number of handle is 312
    
        }
    
```

MSDNのブログかどこかで、Taskに関してはDisposeは実行しなくても問題ない、と書かれたのを見たことがありますが、Disposeを実行してもハンドル数に変化はありません。ハンドルが増えたまま減らないのは非常に気持ち悪いというか、一見するとハンドルリークしているように見えてしまいます。  
Taskを使って大量にスレッド生成するプログラムを書かなきゃいけないのですが、ハンドル数が無限に増えていくようにも見えて正直怖いです。このまま放置してもよいものなのかどうか、それとも何か対処方があるのか、どなたかご存知ないでしょうか？
そもそもハンドル数の上限が決まってるはずなので、放置していいのだろうか、とも思ってます。
CC BY-SA 3.0
2018-01-17T13:47:32.730
41041
2018-01-17T14:11:41.403
27033
question
c# .net
C#のTaskクラスでハンドルリーク？？
`Task`クラスは内部的には`ThreadPool`を使用して処理を実行します。`ThreadPool`はプールですから当然ながら多数の起動されればより必要とされるであろうことを見越して完了したスレッドを保持し次に使いまわすように残されます。  
その上で`Task`クラスはあくまで処理とその結果を保持するクラスですので、`Dispose`を呼び出したとしても処理を実行したスレッドとは無関係であり、スレッド及びそのハンドルが回収されることはありません。

ですので「スレッドプールにより適切に管理されている」で納得していただけたらと思います。より詳細に管理したい場合には[`TaskScheduler`クラス](https://msdn.microsoft.com/ja-
jp/library/system.threading.tasks.taskscheduler\(v=vs.110\).aspx)が用意されていますので、こちらの派生クラスを作成し、動作をカスタマイズすることもできます。
CC BY-SA 3.0
2018-01-17T14:11:41.403
41042
2018-01-17T14:11:41.403
4236
41041
answer