LoginSignup
5
4

More than 1 year has passed since last update.

[C#][備忘録]Task.Start、Task.Run、TaskFactory.StartNewの違い

Last updated at Posted at 2023-01-31

はじめに

処理を別スレッドで行う際によく使用するTaskクラスがあります。
普段業務でTaskを実行するメソッドとしてTask.Run()をよく目にしますが、たまたま最近Task.Start()を利用している箇所を見つけました。
Taskを実行するメソッドで、Run()メソッド以外(たぶん)使ったことが無く、知らなかったためどんな違いがあるのかまとめました。

Task.Run、TaskFactory.StartNew、Task.Startについて

まず、Task.Run()についてです。
タスクのインスタンス化と実行をまとめてできるメソッドです。
マイクロソフトの文書中に、以下の記載がありましたので、TaskFactory.StartNew()についても調べました。

Runメソッドは、既定値を使用してタスクを簡単に開始できるようにする一連のオーバーロードを提供します。これは、StartNewオーバーロードの軽量な代替手段です。

こちらもタスクのインスタンス化と実行をまとめて記述できる書き方です。
こちらの記事によると、Task.RunとTaskFactory.StartNewの大きな違いは、メソッドの引数の複雑さのようです。
Task.RunはTaskFactory.StartNewと同じロジックで実装されていますが、StartNewメソッドで必要な引数を指定しなくても、デフォルトの設定でタスクを実行できるようになっているようでした。

また、記事に以下の記載がありましたので、単純なユースケースの場合はTask.Runを、高度にタスクスケジューラを制御し、パフォーマンスを調整したい場合は、TaskFactory.StartNewを利用するという使い分けのようでした。

In this way, Task.Run can and should be used for the most common cases of simply offloading some work to be processed on the ThreadPool (what TaskScheduler.Default targets). That doesn’t mean Task.Factory.StartNew will never again be used; far from it. Task.Factory.StartNew still has many important (albeit more advanced) uses. You get to control TaskCreationOptions for how the task behaves. You get to control the scheduler for where the task should be queued to and run. You get to use overloads that accept object state, which for performance-sensitive code paths can be used to avoid closures and the corresponding allocations. For the simple cases, though, Task.Run is your friend.
(このように、Task.Run は、ThreadPool 上で処理される作業を単純にオフロードする最も一般的なケース(TaskScheduler.Default が対象)に使用できますし、使用する必要があります。 だからといって、Task.Factory.StartNew が二度と使われなくなるわけではありません。 Task.Factory.StartNew には、(より高度ではありますが)まだ多くの重要な用途があります。 タスクがどのように動作するかについて、TaskCreationOptions を制御することができます。 タスクがどこにキューイングされ、実行されるべきかについて、スケジューラを制御することができます。 オブジェクトの状態を受け取るオーバーロードを使うことができます。これは、パフォーマンスに敏感なコードパスのために、クロージャとそれに対応するアロケーションを避けるために使うことができます。 しかし、単純なケースでは、Task.Runはあなたの友人です。)

Task.Start()

Taskインスタンスをコンストラクタで作成した場合に、そのタスクを実行するためのメソッドです。
上記二つはTaskの作成と実行をまとめているのに対し、こちらは分けたいときに使用するメソッドです。
マイクロソフトの文書に以下の記載がありましたので、Taskの作成と実行を分けたい特別な理由が無いのであれば、Task.RunやTaskFactory.StartNewを使用するのが良さそうです。

For the more common case in which you don't need to separate task instantiation from execution, we recommend that you call an overload of the Task.Run or TaskFactory.StartNew method.
(タスクのインスタンス化と実行を分離する必要がない一般的なケースでは、Task.RunまたはTaskFactory.StartNewメソッドのオーバーロードを呼び出すことをお勧めします。)

さいごに

TaskFactory.StartNewというメソッドがあることは知りませんでした。
また、基本的にはこれからもTask.Runメソッドを使用すれば大体のケースで大丈夫そうだということがわかってよかったです。
勉強になりました。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4