web-dev-qa-db-ja.com

スレッドの作成-Task.Factory.StartNew vs new Thread()

.Net 4の新しいスレッディングおよびパラレルライブラリについて学んでいます。

以前は、(例として)そのように新しいスレッドを作成していました。

DataInThread = new Thread(new ThreadStart(ThreadProcedure));
DataInThread.IsBackground = true;
DataInThread.Start();

今私ができること:

Task t = Task.Factory.StartNew(() =>
{
   ThreadProcedure();
});

違いは何ですか?

ありがとう

97
Jon

大きな違いがあります。タスクはThreadPoolでスケジュールされ、適切な場合は同期的に実行することさえできます。

バックグラウンドで長時間実行されている場合は、正しいタスクオプションを使用してこれを指定する必要があります。

最適化されているため、明示的なスレッド処理よりもタスク並列ライブラリを優先する必要があります。また、継続などの機能があります。

78
sanosdole

タスクは、タスクAPIのすべての長所を提供します。

  • 継続の追加(Task.ContinueWith
  • 複数のタスクが完了するのを待っています(すべてまたはいずれか)
  • タスクのエラーをキャプチャし、後で質問する
  • キャンセルのキャプチャ(およびキャンセルの開始を指定できるようにする)
  • 潜在的に戻り値を持つ
  • C#5でawaitを使用する
  • スケジューリングのより良い制御(長時間実行される場合は、タスクスケジューラがそれを考慮できるようにタスクを作成するときにそうします)

どちらの場合でも、メソッドグループ変換を使用してコードをわずかに単純化できることに注意してください。

DataInThread = new Thread(ThreadProcedure);
// Or...
Task t = Task.Factory.StartNew(ThreadProcedure);
73
Jon Skeet

前者の場合は単に新しいスレッドを開始しているのに対し、後者の場合はスレッドプールに入っています。

スレッドプールジョブは、スレッドを共有およびリサイクルすることです。新しいスレッドを作成する必要があるたびに数ミリ秒の損失を避けることができます。

スレッドプールに入るにはいくつかの方法があります。

  • TPL(タスク並列ライブラリ)を使用して
  • ThreadPool.QueueUserWorkItemを呼び出して
  • デリゲートでBeginInvokeを呼び出すことにより
  • BackgroundWorkerを使用する場合
12
alexandrekow

コードの最初のブロックは、バックグラウンドとして実行できるスレッド(たとえばT)を作成するようにCLRに指示します(Tをスケジュールするときにスレッドプールスレッドを使用します)。簡潔に言うと、CLRに明示的にスレッドを作成して、ユーザーが何かを行うように要求し、スレッドでStart()メソッドを呼び出して開始します。

コードの2番目のブロックも同じですが、タスクファクトリ実装のStartNewメソッドを介して、スレッド(バックグラウンド-スレッドプールで再び実行される)と開始スレッドを作成する責任を委任(暗黙的にハンドオーバー)します。

これは、指定されたコードブロック間の簡単な違いです。とはいえ、グーグルで検索したり、他の投稿者からの他の回答を見ることができる詳細な違いはほとんどありません。

0
s_nair