Apa perbedaan antara tugas dan utas?

378

Di C # 4.0, kita memiliki Taskdalam namespace System.Threading.Tasks . Apa perbedaan sebenarnya antara Threaddan Task. Saya melakukan beberapa program sampel (bantuan diambil dari MSDN) untuk kepentingan saya sendiri belajar

Parallel.Invoke 
Parallel.For 
Parallel.ForEach 

tetapi memiliki banyak keraguan karena idenya tidak begitu jelas.

Saya awalnya mencari di Stackoverflow untuk jenis pertanyaan yang sama tetapi mungkin dengan judul pertanyaan ini saya tidak bisa mendapatkan yang sama. Jika ada yang tahu tentang jenis pertanyaan yang sama yang diposting di sini sebelumnya, silakan berikan referensi tautannya.

hippietrail
sumber
8
utas menjalankan tugas
pm100

Jawaban:

315

Tugas adalah sesuatu yang ingin Anda lakukan.

Thread adalah salah satu dari banyak pekerja yang mungkin melakukan tugas itu.

Dalam istilah .NET 4.0, Tugas mewakili operasi asinkron. Utas digunakan untuk menyelesaikan operasi itu dengan memecah pekerjaan menjadi potongan-potongan dan menugaskan utas terpisah.

Mitch Wheat
sumber
Bisakah Anda memberikan contoh utas yang berfungsi untuk menyelesaikan tugas? Saya tidak tahu apakah utas melakukan pekerjaan yang independen antara satu sama lain atau apakah mereka melakukan perhitungan kerja tim ?
pensum
Kedua skenario dimungkinkan: dalam situasi yang optimal, utas melakukan pekerjaan independen tanpa perlu disinkronkan dengan utas lainnya. Dalam praktiknya, kunci digunakan untuk mengoordinasikan utas.
Mitch Wheat
451

Dalam istilah ilmu komputer, a Taskadalah masa depan atau janji . (Beberapa orang menggunakan kedua istilah itu secara sinonim, beberapa menggunakannya secara berbeda, tidak ada yang bisa menyetujui definisi yang tepat .) Pada dasarnya, sebuah Task<T>"janji" untuk mengembalikan Anda T, tetapi tidak sekarang sayang, saya agak sibuk, kenapa tidak kamu kembali lagi nanti?

A Threadadalah cara untuk memenuhi janji itu. Tetapi tidak setiap orang Taskmembutuhkan yang baru Thread. (Sebenarnya, membuat utas sering kali tidak diinginkan, karena melakukannya jauh lebih mahal daripada menggunakan ulang utas yang ada dari threadpool. Lebih lanjut tentang itu sebentar lagi.) Jika nilai yang Anda tunggu berasal dari sistem file atau database atau jaringan, maka tidak perlu thread untuk duduk dan menunggu data ketika dapat melayani permintaan lainnya. Sebagai gantinya, mereka Taskmungkin mendaftarkan panggilan balik untuk menerima nilai saat mereka siap.

Secara khusus, Tasktidak tidak mengatakan mengapa hal itu adalah bahwa dibutuhkan waktu yang lama untuk kembali nilai. Ini mungkin bahwa dibutuhkan waktu yang lama untuk menghitung, atau mungkin bahwa dibutuhkan waktu yang lama untuk mengambil. Hanya dalam kasus sebelumnya Anda akan menggunakan a Threaduntuk menjalankan a Task. (Dalam. NET, utas sangat mahal, jadi Anda umumnya ingin menghindarinya sebanyak mungkin dan benar-benar hanya menggunakannya jika Anda ingin menjalankan banyak perhitungan berat pada banyak CPU. Misalnya, di Windows, utas berbobot 12 KiByte ( Saya pikir), di Linux, utas berbobot hanya 4 KiByte, di Erlang / BEAM bahkan hanya 400 Byte. Dalam .NET, ini 1 MiByte!)

Jörg W Mittag
sumber
29
Menariknya dalam rilis preview awal TPL (Task Parallel Library) ada Tugas dan Masa Depan <T>. Future <T> kemudian diganti namanya menjadi Tugas <T>. :)
Lee Campbell
23
Bagaimana Anda menghitung 1 MB untuk .NET?
dvallejo
5
@DanVallejo: Angka itu disebutkan dalam sebuah wawancara dengan tim desain TPL. Saya tidak bisa memberi tahu Anda siapa yang mengatakannya atau wawancara apa yang saya tonton beberapa tahun yang lalu.
Jörg W Mittag
9
@RIPUNJAYTRIPATHI Tentu, tapi itu tidak perlu utas lainnya , bisa jadi utas yang meminta pekerjaan di tempat pertama.
Chris Pitman
7
.NET hanya menggunakan utas Windows pada Windows, jadi ukurannya sama - secara default, biasanya 1 MiB memori virtual untuk keduanya. Memori fisik digunakan sesuai kebutuhan dalam potongan berukuran halaman (biasanya 64 kiB), sama dengan kode asli. Ukuran tumpukan ulir minimum tergantung pada OS - 256 kiB untuk Vista, misalnya. Pada x86 Linux, standarnya biasanya 2 MiB - lagi, dialokasikan dalam potongan berukuran halaman. (penyederhanaan) Erlang hanya menggunakan satu utas sistem per proses, 400 byte itu merujuk pada sesuatu yang mirip dengan .NET Task.
Luaan
39

Benang

Hal bare metal, Anda mungkin tidak perlu menggunakannya, Anda mungkin dapat menggunakan LongRunningtugas dan mengambil manfaat dari TPL - Perpustakaan Tugas Paralel, termasuk dalam .NET Framework 4 (februari, 2002) dan di atasnya (juga .NET Inti).

Tugas

Abstraksi di atas Utas. Ia menggunakan kumpulan utas (kecuali jika Anda menetapkan tugas sebagai LongRunningoperasi, jika demikian, utas baru dibuat untuk Anda).

Pool Utas

Seperti namanya: kolam utas. Adalah .NET framework yang menangani sejumlah utas untuk Anda. Mengapa? Karena membuka 100 utas untuk menjalankan operasi CPU yang mahal pada Prosesor dengan hanya 8 core jelas bukan ide yang baik. Kerangka kerja ini akan mempertahankan kumpulan ini untuk Anda, menggunakan kembali utas (tidak membuat / membunuh mereka di setiap operasi), dan mengeksekusi beberapa dari mereka secara paralel, dengan cara yang tidak akan membakar CPU Anda.

OK, tapi kapan harus menggunakan masing-masing?

Dalam resume: selalu gunakan tugas.

Tugas adalah abstraksi, jadi jauh lebih mudah digunakan. Saya menyarankan Anda untuk selalu mencoba menggunakan tugas dan jika Anda menghadapi beberapa masalah yang membuat Anda perlu menangani utas sendiri (mungkin 1% dari waktu) maka gunakan utas.

TAPI sadar bahwa:

  • I / O Bound : Untuk operasi terikat I / O (panggilan basis data, baca / tulis file, panggilan API, dll) hindari menggunakan tugas normal, gunakan LongRunningtugas ( atau utas jika perlu ). Karena menggunakan tugas akan membawa Anda ke kumpulan utas dengan beberapa utas sibuk dan banyak tugas lain menunggu giliran untuk mengambil kumpulan tersebut.
  • CPU Bound : Untuk operasi yang terikat CPU gunakan saja tugas-tugas normal (yang secara internal akan menggunakan thread pool) dan senang.
fabriciorissetto
sumber
sedikit koreksi, sebuah Thread bukanlah "bare-metal thing". itu diimplementasikan oleh OS, sebagian besar implementasi menyampaikan fitur CPU dan CS, tetapi tidak diimplementasikan oleh perangkat keras.
Tomer W
7

Anda dapat menggunakan Taskuntuk menentukan apa yang ingin Anda lakukan kemudian melampirkannya Taskdengan a Thread. sehingga Taskakan dieksekusi di yang baru dibuat Threaddaripada di utas GUI.

Gunakan Taskdengan TaskFactory.StartNew(Action action). Di sini Anda menjalankan delegasi jadi jika Anda tidak menggunakan utas apa pun itu akan dieksekusi di utas yang sama (utas GUI). Jika Anda menyebutkan utas, Anda bisa menjalankan ini Taskdi utas lain. Ini adalah pekerjaan yang tidak perlu karena Anda dapat langsung menjalankan delegasi atau melampirkan delegasi itu ke utas dan mengeksekusi delegasi itu di utas tersebut. Jadi jangan gunakan itu. itu tidak perlu. Jika Anda ingin mengoptimalkan perangkat lunak Anda, ini adalah kandidat yang baik untuk dihapus.

** Harap dicatat bahwa Actionini adalah a delegate.

Gryphes
sumber
6

Selain poin-poin di atas, ada baiknya untuk mengetahui bahwa:

  1. Tugas secara default tugas latar belakang. Anda tidak dapat memiliki tugas latar depan. Di sisi lain utas dapat menjadi latar belakang atau latar depan (Gunakan properti IsBackground untuk mengubah perilaku).
  2. Tugas yang dibuat di kumpulan utas mendaur ulang utas yang membantu menghemat sumber daya. Jadi dalam banyak kasus tugas harus menjadi pilihan default Anda.
  3. Jika operasi cepat, lebih baik menggunakan tugas daripada utas. Untuk operasi yang berjalan lama, tugas tidak memberikan banyak keunggulan dibandingkan utas.
pengguna2492339
sumber
4

Saya biasanya menggunakan Taskuntuk berinteraksi dengan WinForms dan pekerja latar belakang sederhana untuk membuatnya tidak membekukan UI. di sini contoh ketika saya lebih suka menggunakanTask

private async void buttonDownload_Click(object sender, EventArgs e)
{
    buttonDownload.Enabled = false;
    await Task.Run(() => {
        using (var client = new WebClient())
        {
            client.DownloadFile("http://example.com/file.mpeg", "file.mpeg");
        }
    })
    buttonDownload.Enabled = true;
}

VS

private void buttonDownload_Click(object sender, EventArgs e)
{
    buttonDownload.Enabled = false;
    Thread t = new Thread(() =>
    {
        using (var client = new WebClient())
        {
            client.DownloadFile("http://example.com/file.mpeg", "file.mpeg");
        }
        this.Invoke((MethodInvoker)delegate()
        {
            buttonDownload.Enabled = true;
        });
    });
    t.IsBackground = true;
    t.Start();
}

perbedaannya adalah Anda tidak perlu menggunakan MethodInvokerdan kode pendek.

ewwink
sumber
4

Tugas seperti operasi yang ingin Anda lakukan, Thread membantu mengelola operasi tersebut melalui beberapa simpul proses. tugas adalah pilihan ringan karena Threading dapat mengarah pada manajemen kode yang kompleks
Saya akan menyarankan untuk membaca dari MSDN (Terbaik di dunia) selalu

Tugas

Benang

Saurabh
sumber
3

Tugas dapat dilihat sebagai cara yang nyaman dan mudah untuk menjalankan sesuatu secara serempak dan paralel.

Biasanya Tugas adalah semua yang Anda butuhkan, saya tidak ingat apakah saya pernah menggunakan utas untuk hal lain selain eksperimen.

Anda dapat melakukan hal yang sama dengan utas (dengan banyak usaha) sebanyak yang Anda bisa dengan tugas.

Benang

int result = 0;
Thread thread = new System.Threading.Thread(() => { 
    result = 1; 
});
thread.Start();
thread.Join();
Console.WriteLine(result); //is 1

Tugas

int result = await Task.Run(() => {
    return 1; 
});
Console.WriteLine(result); //is 1

Tugas secara default akan menggunakan Threadpool, yang menghemat sumber daya karena membuat utas bisa mahal. Anda dapat melihat Tugas sebagai abstraksi tingkat yang lebih tinggi pada utas.

Seperti yang ditunjukkan artikel ini , tugas menyediakan fitur canggih berikut di utas.

  • Tugas disetel untuk meningkatkan prosesor multicores.

  • Jika sistem memiliki banyak tugas maka ia menggunakan kolam thread CLR secara internal, dan karenanya tidak memiliki overhead yang terkait dengan membuat utas khusus menggunakan Thread. Juga mengurangi waktu perpindahan konteks di antara banyak utas.

  • Tugas dapat mengembalikan hasil. Tidak ada mekanisme langsung untuk mengembalikan hasil dari utas.
  • Tunggu serangkaian tugas, tanpa konstruk pensinyalan.

  • Kita dapat mengaitkan tugas bersama untuk menjalankan satu demi satu.

  • Membangun hubungan orang tua / anak ketika satu tugas dimulai dari tugas lain.

  • Pengecualian tugas anak dapat menyebar ke tugas orang tua.

  • Tugas mendukung pembatalan melalui penggunaan token pembatalan.

  • Implementasi asinkron mudah dilakukan, menggunakan kata kunci 'async' dan 'menunggu'.

CharithJ
sumber