Mengenai penggunaan Task.Start (), Task.Run () dan Task.Factory.StartNew ()


143

Saya baru saja melihat 3 rutinitas mengenai penggunaan TPL yang melakukan pekerjaan yang sama; ini kodenya:

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();                  
}

Aku hanya tidak mengerti mengapa MS memberikan 3 cara yang berbeda untuk menjalankan pekerjaan di TPL karena mereka semua bekerja sama: Task.Start(), Task.Run()dan Task.Factory.StartNew().

Katakan, apakah Task.Start(), Task.Run()dan Task.Factory.StartNew()semua digunakan untuk tujuan yang sama atau apakah mereka memiliki arti yang berbeda?

Kapan sebaiknya satu digunakan Task.Start(), kapan harus digunakan Task.Run()dan kapan harus digunakan Task.Factory.StartNew()?

Tolong bantu saya untuk memahami penggunaan sebenarnya sesuai skenario dengan sangat detail dengan contoh, terima kasih.


ada artikel lama yang menjelaskan bahwa di sini dan di sini untuk yang lebih baruTask.Run - mungkin ini akan menjawab pertanyaan Anda;)
Carsten

Berikut adalah contoh di mana Task.Startsebenarnya berguna.
noseratio

Jawaban:


171

Task.Runadalah singkatan untuk Task.Factory.StartNewdengan argumen aman tertentu:

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

Itu ditambahkan di. Net 4.5 untuk membantu dengan semakin seringnya penggunaan asyncdan pembongkaran pekerjaan ke Internet ThreadPool.

Task.Factory.StartNew(ditambahkan dengan TPL di .Net 4.0) jauh lebih kuat. Anda hanya boleh menggunakannya jika Task.Runtidak cukup, misalnya ketika Anda ingin menggunakan TaskCreationOptions.LongRunning(meskipun itu tidak perlu ketika delegasi adalah async. Lebih lanjut tentang itu di blog saya: LongRunning Tidak Berguna Untuk Tugas. Berjalanlah dengan async-tunggu ). Lebih lanjut tentang Task.Factory.StartNewdi Task.Run vs Task.Factory.StartNew

Jangan pernah membuat Taskdan menelepon Start()kecuali Anda menemukan alasan yang sangat bagus untuk melakukannya. Seharusnya hanya digunakan jika Anda memiliki beberapa bagian yang perlu membuat tugas tetapi tidak menjadwalkannya dan bagian lain yang menjadwalkan tanpa membuat. Itu hampir tidak pernah merupakan solusi yang tepat dan bisa berbahaya. Lebih banyak di "Task.Factory.StartNew" vs "Task baru (...). Mulai"

Kesimpulannya, sebagian besar menggunakan Task.Run, gunakan Task.Factory.StartNewjika Anda harus dan tidak pernah menggunakannya Start.


5
u berkata "Jangan pernah membuat Tugas dan panggil Mulai ()" mengarahkan saya ke setiap penulisan yang bagus yang akan menunjukkan bahwa mungkin disebabkan oleh Task.Start (). Saya perlu detail karena Anda mengatakan untuk menghindarinya. terima kasih atas balasannya.
Mou


1
@ Anda Task.Startmemiliki tempat untuk jenis warisan sebagian besar.
Yuval Itzchakov

1
@ Anda Tidak efisien karena memerlukan sinkronisasi untuk memastikan hanya dipanggil sekali. Pilihan lain tidak.
i3arnon

2
@Mou Anda mungkin harus membaca posting yang menjelaskan masalah ini blogs.msdn.com/b/pfxteam/archive/2010/06/13/10024153.aspx
i3arnon

2

Jawaban singkat :

Jika Anda tidak menggunakan tugas anak-anak bersarang dan selalu ingin tugas Anda dieksekusi di Thread Pool , lebih baik digunakan Task.Run.

Jawaban panjang:

Task.Rundan Task.Factory.StartNewkeduanya memberikan dukungan untuk membuat dan menjadwalkan objek Tugas sehingga kita tidak perlu membuat Taskdan memanggilStart()

Task.Run(action);

Setara dengan:

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

Dan

Task.Factory.StartNew(action);

Setara dengan:

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

Task.Runmenggunakan TaskCreationOptions.DenyChildAttachyang berarti bahwa tugas anak-anak tidak dapat dilampirkan ke orang tua dan itu menggunakan TaskScheduler.Defaultyang berarti bahwa yang menjalankan tugas di Thread Pool akan selalu digunakan untuk menjalankan tugas.

Task.Factory.StartNewmenggunakan TaskScheduler.Currentyang berarti penjadwal utas saat ini, mungkin TaskScheduler.Defaulttapi tidak selalu.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.