Task.Start()、Task.Run()、Task.Factory.StartNew()の使用について


143

同じ仕事をするTPLの使用に関する3つのルーチンを見たところです。ここにコードがあります:

public static void Main()
{
    Thread.CurrentThread.Name = "Main";

    // Create a task and supply a user delegate by using a lambda expression. 
    Task taskA = new Task( () => Console.WriteLine("Hello from taskA."));
    // Start the task.
    taskA.Start();

    // Output a message from the calling thread.
    Console.WriteLine("Hello from thread '{0}'.", 
                  Thread.CurrentThread.Name);
    taskA.Wait();
}

public static void Main()
{
    Thread.CurrentThread.Name = "Main";

    // Define and run the task.
    Task taskA = Task.Run( () => Console.WriteLine("Hello from taskA."));

    // Output a message from the calling thread.
    Console.WriteLine("Hello from thread '{0}'.", 
                      Thread.CurrentThread.Name);
    taskA.Wait();
}

public static void Main()
{
    Thread.CurrentThread.Name = "Main";

    // Better: Create and start the task in one operation. 
    Task taskA = Task.Factory.StartNew(() => Console.WriteLine("Hello from taskA."));

    // Output a message from the calling thread.
    Console.WriteLine("Hello from thread '{0}'.", 
                    Thread.CurrentThread.Name);

    taskA.Wait();                  
}

私はちょうどMSが同じTPLに彼らなぜならすべての作業をジョブを実行するには3種類の方法を与える理由を理解していない:Task.Start()Task.Run()Task.Factory.StartNew()

教えてください、ありTask.Start()Task.Run()そしてTask.Factory.StartNew()すべて同じ目的のために使用されるか、またはそれらは異なる意味を持っていますか?

いつ使うべきかTask.Start()、いつ使うべきか、いつ使うTask.Run()べきTask.Factory.StartNew()か?

シナリオごとの実際の使用法を、例を挙げて非常に詳しく理解できるように私に助けてください、ありがとうございます。


そこにあることをここ説明古い記事新しいのために、ここではTask.Run -多分これは、あなたの質問にお答えします。)
カルステン

以下は、Task.Start実際に役立つ例です。
noseratio

回答:


171

Task.RunTask.Factory.StartNew特定の安全な引数を持つ省略形です:

Task.Factory.StartNew(
    action, 
    CancellationToken.None, 
    TaskCreationOptions.DenyChildAttach, 
    TaskScheduler.Default);

.Net 4.5で追加され、ますます頻繁に使用されるようにasyncなり、作業をThreadPool

Task.Factory.StartNew(.Net 4.0のTPLで追加)は、はるかに堅牢です。Task.RunたとえばTaskCreationOptions.LongRunning、デリゲートが非同期の場合は不要ですが、使用する場合など、十分でない場合にのみ使用する必要があります。詳細については、ブログの「LongRunning Is Useless For Task.Run With async-await」を参照してください。もっと上Task.Factory.StartNewTask.Factory.StartNew対Task.Run

非常に正当な理由がない限り、Taskand呼び出しを作成しないでくださいStart()。タスクを作成する必要があるがタスクをスケジュールする必要がない部分と、作成せずにスケジュールする別の部分がある場合にのみ使用してください。それはほとんど決して適切な解決策ではなく、危険かもしれません。もっとにおける対「Task.Factory.StartNew」「新しいタスク(...)。スタート」

結論として、主にを使用しTask.Run、使用Task.Factory.StartNewする必要がある場合と使用しない場合に使用しますStart


5
u「タスクを作成してStart()を呼び出さないでください」と言った場合、Task.Start()が原因である可能性があることを示す適切な書き込みにリダイレクトされます。あなたがそれを避けるために言っているので、私は詳細が必要です。返信ありがとうございます。
Mou

ruこのリンクについて話しているblogs.msdn.com/b/pfxteam/archive/2010/06/13/10024153.aspx ??
Mou

1
@Mou Task.Startは主に型を継承する場所を持っています。
Yuval Itzchakov 2015

1
@Mou一度だけ呼び出されることを確認するには同期が必要なので、非効率的です。他のオプションはありません。
i3arnon 2015

2
@Mouこの問題を説明する投稿を読んでくださいblogs.msdn.com/b/pfxteam/archive/2010/06/13/10024153.aspx
i3arnon

2

短い答え

ネストされた子のタスクを使用せず、常にタスクをスレッドプールで実行する場合は、を使用することをお勧めしますTask.Run

長い答え:

Task.Runそして、 Task.Factory.StartNewの両方を作成するためのサポートを提供し、私たちが作成する必要はありませんので、スケジューリングタスクは、オブジェクトTaskとコールをStart()

Task.Run(action);

以下と同等です。

Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);

そして

Task.Factory.StartNew(action);

以下と同等です。

Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current);

Task.Run用途TaskCreationOptions.DenyChildAttachいる子供たちのタスクは、親に接続することはできませんし、それが使用することを意味しTaskScheduler.Defaultている手段スレッドプールで実行するタスクは常にタスクを実行するために使用されることが1という。

Task.Factory.StartNew用途TaskScheduler.Current現在のスレッドのスケジューラを意味し、それはあるかもしれないTaskScheduler.Defaultが、常にではありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.