Saya punya Metode:
private static void Method()
{
Console.WriteLine("Method() started");
for (var i = 0; i < 20; i++)
{
Console.WriteLine("Method() Counter = " + i);
Thread.Sleep(500);
}
Console.WriteLine("Method() finished");
}
Dan saya ingin memulai metode ini dalam Tugas baru. Saya dapat memulai tugas baru seperti ini
var task = Task.Factory.StartNew(new Action(Method));
atau ini
var task = Task.Run(new Action(Method));
Tetapi apakah ada perbedaan antara Task.Run()
dan Task.Factory.StartNew()
. Keduanya menggunakan ThreadPool dan memulai Metode () segera setelah membuat instance dari Tugas. Kapan kita harus menggunakan varian pertama dan kapan kedua?
c#
multithreading
task-parallel-library
Sergiy Lichenko
sumber
sumber
StartNew
penggunaan defaultTaskScheduler.Current
yang mungkin merupakan kumpulan utas tetapi juga bisa menjadi utas UI.Jawaban:
Metode kedua
Task.Run
,, telah diperkenalkan di versi terbaru dari kerangka .NET (dalam .NET 4.5).Namun, metode pertama
Task.Factory.StartNew
,, memberi Anda kesempatan untuk mendefinisikan banyak hal bermanfaat tentang utas yang ingin Anda buat, sementaraTask.Run
tidak menyediakan ini.Misalnya, katakanlah Anda ingin membuat utas tugas yang berjalan lama. Jika utas kumpulan utas akan digunakan untuk tugas ini, maka ini bisa dianggap penyalahgunaan utas utas.
Satu hal yang dapat Anda lakukan untuk menghindari ini adalah menjalankan tugas di utas terpisah. Utas yang baru dibuat yang akan didedikasikan untuk tugas ini dan akan dihancurkan begitu tugas Anda selesai. Anda tidak dapat mencapai ini dengan
Task.Run
, sementara Anda dapat melakukannya denganTask.Factory.StartNew
, seperti di bawah ini:Seperti yang dinyatakan di sini :
sumber
that’s exactly equivalent to
itu tidak berlaku.tha's exactly equivalent to
tidak dimiliki oleh frasa . Terima kasih sebelumnya. Akan menyenangkan untuk menjelaskan dengan mengomentari kode Anda. Terima kasih :)TaskScheduler.Default
. Silakan lihat di sini Referenceource.microsoft.com/#mscorlib/system/threading/Tasks/… .Orang sudah menyebutkan itu
Setara dengan
Tapi tidak ada yang menyebutkan itu
Setara dengan:
Seperti yang Anda lihat, dua parameter berbeda untuk
Task.Run
danTask.Factory.StartNew
:TaskCreationOptions
-Task.Run
PenggunaanTaskCreationOptions.DenyChildAttach
yang berarti bahwa tugas anak-anak tidak dapat dilampirkan ke orang tua, pertimbangkan ini:Ketika kita memohon
parentTask.Wait()
,childTask
tidak akan ditunggu, meskipun kita ditentukanTaskCreationOptions.AttachedToParent
untuk itu, ini karenaTaskCreationOptions.DenyChildAttach
melarang anak untuk melampirkan padanya. Jika Anda menjalankan kode yang sama denganTask.Factory.StartNew
alih - alihTask.Run
,parentTask.Wait()
akan menungguchildTask
karenaTask.Factory.StartNew
digunakanTaskCreationOptions.None
TaskScheduler
-Task.Run
MenggunakanTaskScheduler.Default
yang berarti bahwa penjadwal tugas default (yang menjalankan tugas di Thread Pool) akan selalu digunakan untuk menjalankan tugas.Task.Factory.StartNew
di sisi lain menggunakanTaskScheduler.Current
yang berarti penjadwal utas saat ini, mungkinTaskScheduler.Default
tapi tidak selalu. Bahkan ketika mengembangkanWinforms
atauWPF
aplikasi itu diperlukan untuk memperbarui UI dari utas saat ini, untuk melakukan ini orang menggunakanTaskScheduler.FromCurrentSynchronizationContext()
penjadwal tugas, jika Anda tidak sengaja membuat tugas lain yang berjalan di dalam tugas yang digunakanTaskScheduler.FromCurrentSynchronizationContext()
penjadwal UI akan beku. Penjelasan lebih rinci tentang ini dapat ditemukan di siniJadi secara umum jika Anda tidak menggunakan tugas anak bersarang dan selalu ingin tugas Anda dieksekusi di Thread Pool lebih baik digunakan
Task.Run
, kecuali jika Anda memiliki beberapa skenario yang lebih kompleks.sumber
Lihat artikel blog ini yang menjelaskan perbedaannya. Pada dasarnya melakukan:
Sama seperti melakukan:
sumber
The
Task.Run
punya diperkenalkan dalam versi NET framework yang lebih baru dan itu dianjurkan .The
Task.Factory.StartNew
memiliki lebih banyak pilihan,Task.Run
adalah singkatan a:Dan dengan singkatan Maksudku teknis pintas :
sumber
Menurut posting ini oleh Stephen Cleary, Task.Factory.StartNew () berbahaya:
Berikut alasan sebenarnya:
Jadi itu berarti bisa berpotensi berjalan di utas UI jika operasi selesai dan ini marshal kembali ke utas UI karena kelanjutan sebagai Stephen Cleary menjelaskan lebih lengkap di posnya.
Dalam kasus saya, saya mencoba menjalankan tugas di latar belakang saat memuat datagrid untuk tampilan sementara juga menampilkan animasi yang sibuk. Animasi sibuk tidak ditampilkan saat menggunakan
Task.Factory.StartNew()
tetapi animasi ditampilkan dengan benar ketika saya beralih keTask.Run()
.Untuk detailnya, silakan lihat https://blog.stephencleary.com/2013/08/startnew-is-dangerous.html
sumber
Terlepas dari kesamaan yaitu Task.Run () menjadi singkatan untuk Task.Factory.StartNew (), ada perbedaan menit antara perilaku mereka dalam kasus sinkronisasi dan delegasi async.
Misalkan ada dua metode berikut:
Sekarang perhatikan kode berikut.
Di sini, sync1 dan sync2 bertipe Task <int>
Namun, ada perbedaan dalam hal metode async.
Dalam skenario ini, async1 bertipe Task <int>, namun async2 bertipe Task <Task <int>>
sumber
Task.Run
telah built-in fungsionalitasUnwrap
metode membuka . Berikut adalah posting blog yang menjelaskan alasan di balik keputusan ini.Dalam aplikasi saya yang memanggil dua layanan, saya membandingkan Task.Run dan Task.Factory.StartNew . Saya menemukan bahwa dalam kasus saya keduanya bekerja dengan baik. Namun, yang kedua lebih cepat.
sumber