Membuat utas - Task.Factory.StartNew vs Thread baru ()


102

Saya baru saja belajar tentang pustaka Threading dan Paralel baru di .Net 4

Di masa lalu saya akan membuat Thread baru seperti itu (sebagai contoh):

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

Sekarang saya bisa melakukan:

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

Apa bedanya jika ada?

Terima kasih


1
Anda perlu sedikit khawatir tentang cara kerja penjadwal kumpulan utas. Ini bisa membuat perbedaan besar tetapi itu semua tergantung pada apa yang sebenarnya Anda lakukan di dalam utas.
Hans Passant

Jawaban:


79

Ada perbedaan besar. Tugas dijadwalkan di ThreadPool dan bahkan dapat dijalankan secara sinkron jika sesuai.

Jika Anda memiliki pekerjaan latar belakang yang berjalan lama, Anda harus menentukan ini dengan menggunakan Opsi Tugas yang benar.

Anda sebaiknya lebih memilih Task Parallel Library daripada penanganan utas eksplisit, karena ini lebih dioptimalkan. Anda juga memiliki lebih banyak fitur seperti Kelanjutan.


5
Tidak, tidak. Itu hanya memulai tugas. Ini bisa mengantrekan tugas di kumpulan thread atau menjalankannya secara sinkron. TPL adalah tentang membebaskan Anda dari mengelola sendiri utas / konkurensi dan menggunakan yang terbaik untuk platform Anda (seperti memanfaatkan inti)
sanosdole

10
Ada opsi TaskCreationOptions.LongRunning yang akan selalu membuat utas lain, tetapi intinya adalah mengapa Anda membutuhkan utas lain? Jika Anda hanya ingin melakukan sesuatu secara paralel (Utama melakukan sth. Saat Tugas berjalan) lebih baik membiarkan perpustakaan yang dioptimalkan memutuskan bagaimana memanfaatkan sumber daya sistem seperti utas untuk melakukan ini dengan cara yang paling efisien.
sanosdole

3
Artikel msdn ini menjelaskan bagaimana tugas dijadwalkan. Ini mencakup longrunning & inlining (eksekusi sinkron). msdn.microsoft.com/en-us/library/dd997402.aspx
sanosdole

2
@sming Intinya adalah Anda ingin memproses secara bersamaan (tidak memblokir UI) bukan karena Anda menginginkan utas baru. ThreadPool tidak akan memblokir thread UI, tetapi mengelola thread latar belakang jauh lebih efisien daripada yang dapat Anda lakukan secara manual dengan membuat thread. Itulah proses perubahan pikiran yang diperkenalkan oleh TPL. Jangan pikirkan utas, pikirkan tugas yang bersamaan.
sanosdole

4
@sming Maaf, kalimat itu agak terlalu kasar. Eksekusi tugas secara sinkron disebut sebaris. Saat menjadwalkan tugas di threadpool (penjadwal default) dari UI Thread, hal itu tidak akan terjadi. Ini hanya akan terjadi jika penjadwal ambien ('TaskScheduler.Current') sama dengan penjadwal tugas yang Anda panggil '.Wait ()' di. Karena '.Wait ()' memblokir, itu akan tetap memblokir UI. Singkatnya: Jangan panggil tunggu dan itu tidak akan dijalankan secara serempak.
sanosdole

74

Tugas memberi Anda semua kebaikan API tugas:

  • Menambahkan lanjutan ( Task.ContinueWith)
  • Menunggu beberapa tugas untuk diselesaikan (baik semua atau apa pun)
  • Menangkap kesalahan dalam tugas dan menginterogasinya nanti
  • Menangkap pembatalan (dan memungkinkan Anda menentukan pembatalan untuk memulai)
  • Berpotensi memiliki nilai pengembalian
  • Menggunakan menunggu di C # 5
  • Kontrol yang lebih baik atas penjadwalan (jika itu akan berjalan lama, katakan demikian saat Anda membuat tugas sehingga penjadwal tugas dapat memperhitungkannya)

Perhatikan bahwa dalam kedua kasus, Anda dapat membuat kode Anda sedikit lebih sederhana dengan konversi grup metode:

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

8
+1. Saya ingin menambahkan itu Threadtingkat yang sangat rendah dibandingkan dengan Task(Saya memiliki posting blog yang menjelaskan secara rinci). Saya memberikan ceramah tentang "menggunakan Tasks di dunia nyata" di Grand Rapids DevDay . Pembicaraan ini disebut "Thread is Dead", karena tidak diperlukan lagi Thread(kecuali Anda mengimplementasikan a TaskScheduler).
Stephen Cleary

@StephenCleary, saya berasumsi bahwa maksud Anda Threadsudah mati, saat digunakan sebagai thread latar belakang?
surut

1
@ebb: Tidak, saya mengambil posisi yang lebih kuat yang dijelaskan dalam komentar pertama saya. Tidak ada yang Threadbisa dilakukan (atau BackgroundWorker) yang tidak bisa dilakukan dengan lebih elegan Taskdan pantas TaskScheduler.
Stephen Cleary

1
@StephenCleary, Bagaimana Anda akan membuat utas khusus, tanpa menggunakan Thread?
surut

4
@ebb: "Utas khusus" tidak jelas bagi saya. Jika Anda ingin a Taskdijalankan pada utas tertentu, gunakan yang sesuai TaskScheduler- mis AsyncContextThread. , . Namun, ini biasanya tidak perlu; itu SynchronizationContext,, ThreadPooldan ConcurrentExclusiveSchedulerPairpenjadwal cukup untuk sebagian besar program.
Stephen Cleary

12

Dalam kasus pertama Anda hanya memulai utas baru sementara dalam kasus kedua Anda masuk ke kumpulan utas.

Tugas kumpulan utas adalah membagikan dan mendaur ulang utas. Ini memungkinkan untuk menghindari kehilangan beberapa milidetik setiap kali kita perlu membuat utas baru.

Ada beberapa cara untuk memasuki kumpulan utas:

  • dengan TPL (Task Parallel Library) seperti yang Anda lakukan
  • dengan memanggil ThreadPool.QueueUserWorkItem
  • dengan memanggil BeginInvoke pada seorang delegasi
  • saat Anda menggunakan BackgroundWorker

1

Blok kode pertama Anda memberi tahu CLR untuk membuat Thread (katakanlah. T) untuk Anda yang dapat dijalankan sebagai latar belakang (gunakan thread pool thread saat menjadwalkan T). Singkatnya, Anda secara eksplisit meminta CLR untuk membuat utas agar Anda melakukan sesuatu dan memanggil metode Start () pada utas untuk memulai.

Blok kode kedua Anda melakukan hal yang sama tetapi mendelegasikan (secara implisit menyerahkan) tanggung jawab untuk membuat utas (latar belakang- yang lagi-lagi berjalan di kumpulan utas) dan utas awal melalui metode StartNew dalam implementasi Pabrik Tugas.

Ini adalah perbedaan cepat antara blok kode yang diberikan. Karena itu, ada beberapa perbedaan mendetail yang dapat Anda gunakan di google atau lihat jawaban lain dari rekan kontributor saya.

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.