Pada metode Task.Factory.StartNew dan Task.Run

Saat membuat tugas menggunakan metode Task.Factory.StartNew atau Task.Run, Anda harus mengingat poin penting tertentu saat menulis kode asinkron. Dalam kebanyakan kasus, disarankan untuk menghindari penggunaan metode Task.Factory.StartNew jika Anda bekerja dengan kode asinkron. Jika Anda bekerja dengan kode paralel, saya akan mengatakan bahwa StartNew adalah pilihan yang baik.

Penjadwal tugas adalah komponen yang bertanggung jawab untuk menjadwalkan tugas; Kerangka .Net memberi Anda dua penjadwal tugas. Ada penjadwal tugas default yang berjalan di kumpulan utas kerangka .Net, dan ada penjadwal tugas yang mengeksekusi pada konteks sinkronisasi dari target yang ditentukan. Penjadwal tugas default akan mencukupi sebagian besar waktu, tetapi Anda juga dapat membuat penjadwal tugas kustom Anda sendiri untuk menyediakan fungsionalitas tambahan. Untuk membuat penjadwal tugas kustom Anda sendiri, Anda perlu membuat kelas yang memperluas kelas System.Threading.Tasks.TaskScheduler.

Bagaimana cara membuat Tasks menggunakan Task Parallel Library?

Ada beberapa cara untuk membuat dan memulai tugas di .Net. Anda perlu menggunakan kelas System.Threading.Tasks.Task atau System.Threading.Tasks.Task untuk membuat tugas (unit kerja yang dapat dijadwalkan). Sementara yang pertama digunakan untuk membuat tugas yang tidak mengembalikan nilai, yang terakhir digunakan untuk membuat tugas yang memiliki nilai yang dikembalikan. Properti Task.Factory adalah turunan dari kelas TaskFactory. Properti ini digunakan untuk membuat dan menjadwalkan tugas. Sementara metode Task.Factory.StartNew bekerja seperti operasi garpu dan digunakan untuk membuat dan memulai tugas baru, metode Tunggu bekerja seperti operasi gabungan dan menunggu tugas selesai.

Potongan kode berikut mengilustrasikan bagaimana Anda dapat menggunakan metode Task.Factory.StartNew.

Task.Factory.StartNew(() => TestMethod(), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);

Anda juga dapat membuat Tugas menggunakan metode Task.Run seperti yang ditunjukkan pada potongan kode di bawah ini.

public async Task DoSomeWork()

        {

            await Task.Run(() => TestMethod());

        }

        void TestMethod()

        {

            Console.WriteLine("Hello world!");

        }

Jika Anda ingin mengembalikan nilai dari Task, Anda dapat memanfaatkan metode Task.FromResult seperti yang ditunjukkan dalam cuplikan kode di bawah ini.

public async Task DoSomeWork()

   {

      string text = await Task.FromResult(GetMessage());

   }

private string GetMessage()

   {

      return "Hello world!";

   }

Anda juga dapat membuat tugas menggunakan delegasi atau tindakan. Cuplikan kode berikut menunjukkan bagaimana Anda dapat membuat tugas menggunakan tindakan dan delegasi.

Task task1 = new Task (new Action(Display));

task1.Start();

Task task2 = new Task (delegate { Display(); });

task2.Start();

Anda juga dapat membuat tugas menggunakan metode lamba dan anonim.

Task.Factory.StartNew dan Task.Run

Task.Factory.StartNew adalah cara cepat untuk membuat dan memulai Task. Perhatikan bahwa panggilan ke Task.Factory.StartNew secara fungsional setara dengan membuat instance tugas dan kemudian memanggil metode Start pada instance tersebut. Namun, tidak disarankan untuk digunakan karena banyak alasan. Jika Anda ingin menjalankan kode sinkron, Task.Factory.StartNew bukanlah pilihan yang baik.

Perhatikan bahwa jika penjadwal tugas tersedia, metode StartNew akan menjalankan tugas pada penjadwal tugas tersebut. Sebaliknya, jika penjadwal tidak tersedia, penjadwal akan menjalankan tugas pada utas kumpulan utas. Perlu dicatat bahwa Task.Factory.StartNew default ke TaskScheduler.Current dan bukan TaskScheduler.Default.

Perhatikan bahwa panggilan ke Task.Run (tindakan) setara dengan pernyataan berikut: Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);

Sebaliknya, panggilan ke Task.Factory.StartNew (tindakan) setara dengan pernyataan berikut:

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

Jika mungkin ingin menggunakan Task.Factory.StartNew jika Anda telah membuat penjadwal tugas kustom dan meneruskan instance scheduler secara eksplisit. Saya selalu merekomendasikan menggunakan Task.Run karena jauh lebih sederhana dan memiliki default yang lebih aman. Dengan kata lain, kita harus menghindari penggunaan Task.Factory.StartNew kecuali jika ada kebutuhan untuk membuat penjadwal tugas dan kemudian meneruskannya secara eksplisit saat memanggil metode StartNew untuk membuat tugas baru dan menjadwalkannya. Jika Anda akan menggunakan metode TaskFactory.StartNew secara efektif dan andal, Anda harus menggunakan penjadwal tugas khusus dan kemudian menentukan CancellationToken dan TaskCreationOptions.

Metode Task.Run direkomendasikan untuk digunakan saat Anda tidak perlu memiliki banyak kendali atas penjadwalan thread dan kerumitannya. Anda harus menggunakan Task.Run terutama pada metode terikat CPU. Namun, Anda harus menggunakan Task.Run saat menjalankan tugas dan tidak di dalam implementasi tugas. Dengan kata lain, Anda harus menggunakan Task.Run tidak di dalam implementasi metode apa pun, tetapi pada titik di mana metode tersebut dipanggil. Sebagai contoh, potongan kode berikut adalah contoh potongan kode yang "buruk".

public async Task DownloadDataFromWebAsync(Uri uri)

        {

            return await Task.Run(() =>

            {

                using (WebClient webClient = new WebClient())

                {

                    return webClient.DownloadString(uri);

                }

            });

        }

Lihat potongan kode yang diberikan di atas. Metode ini tidak skalabel karena akan memblokir utas latar belakang, mengambil utas dari kumpulan utas, dan mengeksekusi secara sinkron. Karenanya, ini akan menghabiskan lebih banyak sumber daya di sistem Anda.