2012-06-17 13 views
7

私は、TPLを使用して、機能Task.Factory.StartNew()を使用して新しいタスクをシステムスレッドプールに追加しています。唯一の問題は、スレッドをたくさん追加していることです。プロセッサが処理するには多すぎるスレッドを作成していると思います。このスレッドプールに最大スレッド数を設定する方法はありますか?TPLを使用する最大スレッドプールサイズを設定するには

+3

だけで考えてはいけませんそれが実際に本当であるかどうかを調べる。 – svick

+0

コードサンプルはありますか? –

答えて

12

デフォルト値TaskSchedulerTaskScheduler.Defaultから取得)は、(内部クラス)ThreadPoolTaskSchedulerです。この実装では、ThreadPoolクラスを使用してタスクをキューに入れます(Taskが​​で作成されていない場合 - この場合、タスクごとに新しいスレッドが作成されます)。

あなたはnew Task(() => Console.WriteLine("In task"))を介して作成Taskオブジェクトに使用可能なスレッドの#を制限したいのであれば、あなたは、このようなグローバルスレッドプールで使用可能なスレッドを制限することができます

// Limit threadpool size 
int workerThreads, completionPortThreads; 
ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads); 
workerThreads = 32; 
ThreadPool.SetMaxThreads(workerThreads, completionPortThreads); 

ThreadPool.GetMaxThreads()への呼び出しをするために行われますcompletionPortThreadsの縮小を避けてください。

これは悪い考えであってもよいこと注 - 指定されたスケジューラなく、すべてのタスク以来、および他のクラスの任意の数が少なすぎるサイズを設定、デフォルトのThreadPoolを使用して副作用を引き起こす可能性:飢餓など

3

を参照してください。まず、パフォーマンスの問題を調査する必要があります。

  • LongRunningTaskオプション
  • せずに長時間実行タスクのスケジュールと同じWebアドレスにアクセスするためのブロッキング
  • に二つ以上の同時接続をオープンしようとしている:縮小利用になることがあり、様々な問題があります。あなたは、単に対処することができないスケーラビリティの問題を持っているどのような場合には、複数のスレッド

からの呼び出しを(使用してUIスレッドにアクセスしようとすると、同じリソース

  • )同時並行タスクの数を減らすことによって達成される。あなたのプログラムは、将来、2コア、4コア、または8コアのマシンで動作するかもしれません。スケジュールされたタスクの数を制限するだけでは、CPUリソースの無駄になります。

  • +1

    downvote、ありがとう、ありがとう、ありがとう?一般的なバグは、Tasksがスレッドと等しいと仮定してタスクの数を制限しようとしているため、パフォーマンス上の問題がさらに深刻化します。 –

    -1

    通常、TPLスケジューラは並行して実行するタスクをいくつでも選択することができますが、実際に制御する場合は、My blog postは、タスクとアクションの両方でこれを行う方法を示し、ダウンロードできるサンプルプロジェクトを提供します両方を実際に見るために走っています。

    独自のサービスを呼び出していてサーバーを過負荷にしたくない場合に同時に実行されるタスクの数を明示的に制限したい場合の例です。

    あなたが説明していることは、無駄なスレッド消費を防ぐためにタスクで非同期/待機を使用していることを確認することにより多くのメリットがあるようです。これは、CPUバインドされた作業、またはIOバインドされた作業をタスクで実行している場合に依存します。それがIOバウンドの場合、async/awaitを使用することで大きな利益を得ることができます。

    どのように同時に実行するタスクの数を制限できるか尋ねたので、アクションとタスクの両方でそれを行う方法を示すコードをいくつか示します。アクションを使用している場合はアクション

    、あなたは内蔵のネットParallel.Invoke機能を使用することができます。ここでは最大3つのスレッドを並列に実行するように制限しています。タスク

    var listOfActions = new List<Action>(); 
    for (int i = 0; i < 10; i++) 
    { 
        // Note that we create the Action here, but do not start it. 
        listOfActions.Add(() => DoSomething()); 
    } 
    
    var options = new ParallelOptions {MaxDegreeOfParallelism = 3}; 
    Parallel.Invoke(options, listOfActions.ToArray()); 
    

    あなたはここでのタスクを使用しているので、しかし、何の組み込み関数はありません。しかし、あなたは自分のブログで私が提供しているものを使うことができます。 3つの同時の最大が一度に言うと、あなたがこれを行うことが

    /// <summary> 
        /// Starts the given tasks and waits for them to complete. This will run, at most, the specified number of tasks in parallel. 
        /// <para>NOTE: If one of the given tasks has already been started, an exception will be thrown.</para> 
        /// </summary> 
        /// <param name="tasksToRun">The tasks to run.</param> 
        /// <param name="maxTasksToRunInParallel">The maximum number of tasks to run in parallel.</param> 
        /// <param name="cancellationToken">The cancellation token.</param> 
        public static void StartAndWaitAllThrottled(IEnumerable<Task> tasksToRun, int maxTasksToRunInParallel, CancellationToken cancellationToken = new CancellationToken()) 
        { 
         StartAndWaitAllThrottled(tasksToRun, maxTasksToRunInParallel, -1, cancellationToken); 
        } 
    
        /// <summary> 
        /// Starts the given tasks and waits for them to complete. This will run, at most, the specified number of tasks in parallel. 
        /// <para>NOTE: If one of the given tasks has already been started, an exception will be thrown.</para> 
        /// </summary> 
        /// <param name="tasksToRun">The tasks to run.</param> 
        /// <param name="maxTasksToRunInParallel">The maximum number of tasks to run in parallel.</param> 
        /// <param name="timeoutInMilliseconds">The maximum milliseconds we should allow the max tasks to run in parallel before allowing another task to start. Specify -1 to wait indefinitely.</param> 
        /// <param name="cancellationToken">The cancellation token.</param> 
        public static void StartAndWaitAllThrottled(IEnumerable<Task> tasksToRun, int maxTasksToRunInParallel, int timeoutInMilliseconds, CancellationToken cancellationToken = new CancellationToken()) 
        { 
         // Convert to a list of tasks so that we don&#39;t enumerate over it multiple times needlessly. 
         var tasks = tasksToRun.ToList(); 
    
         using (var throttler = new SemaphoreSlim(maxTasksToRunInParallel)) 
         { 
          var postTaskTasks = new List<Task>(); 
    
          // Have each task notify the throttler when it completes so that it decrements the number of tasks currently running. 
          tasks.ForEach(t => postTaskTasks.Add(t.ContinueWith(tsk => throttler.Release()))); 
    
          // Start running each task. 
          foreach (var task in tasks) 
          { 
           // Increment the number of tasks currently running and wait if too many are running. 
           throttler.Wait(timeoutInMilliseconds, cancellationToken); 
    
           cancellationToken.ThrowIfCancellationRequested(); 
           task.Start(); 
          } 
    
          // Wait for all of the provided tasks to complete. 
          // We wait on the list of "post" tasks instead of the original tasks, otherwise there is a potential race condition where the throttler&#39;s using block is exited before some Tasks have had their "post" action completed, which references the throttler, resulting in an exception due to accessing a disposed object. 
          Task.WaitAll(postTaskTasks.ToArray(), cancellationToken); 
         } 
        } 
    

    [タスクのリストを作成し、それらを実行させる機能を呼び出して、:

    var listOfTasks = new List<Task>(); 
    for (int i = 0; i < 10; i++) 
    { 
        var count = i; 
        // Note that we create the Task here, but do not start it. 
        listOfTasks.Add(new Task(() => Something())); 
    } 
    Tasks.StartAndWaitAllThrottled(listOfTasks, 3); 
    

    関連する問題