Pada kaedah Task.Factory.StartNew dan Task.Run

Semasa membuat tugas menggunakan kaedah Task.Factory.StartNew atau Task.Run, anda harus ingat perkara penting tertentu semasa menulis kod tak segerak. Dalam kebanyakan kes, disarankan untuk tidak menggunakan kaedah Task.Factory.StartNew jika anda menggunakan kod tak segerak. Sekiranya anda menggunakan kod selari, saya akan mengatakan bahawa StartNew adalah pilihan yang baik.

Penjadual tugas adalah komponen yang bertanggungjawab untuk menjadwalkan tugas; Rangka kerja .Net memberi anda dua penjadual tugas. Terdapat penjadual tugas lalai yang berjalan di kumpulan utas kerangka .Net, dan ada penjadual tugas yang menjalankan konteks penyegerakan dari sasaran yang ditentukan. Penjadual tugas lalai akan mencukupi sepanjang masa, tetapi anda juga dapat membuat penjadual tugas khusus anda sendiri untuk memberikan fungsi tambahan. Untuk membina penjadual tugas khas anda sendiri, anda perlu membuat kelas yang memanjangkan kelas System.Threading.Tasks.TaskScheduler.

Bagaimana saya membuat Tugas menggunakan Perpustakaan Selari Tugas?

Terdapat beberapa cara di mana anda boleh membuat dan memulakan tugas di .Net. Anda perlu menggunakan System.Threading.Tasks.Task atau System.Threading.Tasks.Task class untuk membuat tugas (unit kerja yang boleh dijadualkan). Sementara yang pertama digunakan untuk membuat tugas yang tidak mengembalikan nilai, yang terakhir digunakan untuk membuat tugas yang memiliki nilai kembali. Properti Task.Factory adalah contoh kelas TaskFactory. Properti ini digunakan untuk membuat dan menjadualkan tugas. Walaupun kaedah Task.Factory.StartNew berfungsi seperti operasi garpu dan digunakan untuk membuat dan memulakan tugas baru, kaedah Tunggu berfungsi sama seperti operasi bergabung dan menunggu tugas selesai.

Coretan kod berikut menggambarkan bagaimana anda boleh menggunakan kaedah Task.Factory.StartNew.

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

Anda juga boleh membuat Task menggunakan kaedah Task.Run seperti yang ditunjukkan dalam coretan kod di bawah.

public async Task DoSomeWork()

        {

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

        }

        void TestMethod()

        {

            Console.WriteLine("Hello world!");

        }

Sekiranya anda ingin mengembalikan nilai dari Task, anda boleh memanfaatkan kaedah Task.FromResult seperti yang ditunjukkan dalam coretan kod di bawah.

public async Task DoSomeWork()

   {

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

   }

private string GetMessage()

   {

      return "Hello world!";

   }

Anda juga boleh membuat tugas menggunakan perwakilan atau tindakan. Coretan kod berikut menunjukkan bagaimana anda dapat membuat tugas menggunakan tindakan dan perwakilan.

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

task1.Start();

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

task2.Start();

Anda juga boleh membuat tugas menggunakan kaedah lamba dan tanpa nama.

Task.Factory.StartNew dan Task.Run

Task.Factory.StartNew adalah cara cepat untuk membuat dan memulakan Tugas. Perhatikan bahawa panggilan ke Task.Factory.StartNew berfungsi sama dengan membuat tugas tugas dan kemudian memanggil kaedah Mula pada instance. Walau bagaimanapun, tidak digalakkan untuk digunakan dengan banyak alasan. Sekiranya anda ingin melaksanakan kod segerak, Task.Factory.StartNew bukanlah pilihan yang baik.

Perhatikan bahawa jika penjadual tugas tersedia, kaedah StartNew akan menjalankan tugas pada penjadual tugas tersebut. Sebaliknya, jika penjadual tidak tersedia, ia akan melaksanakan tugas tersebut pada thread kumpulan utas. Perlu diingatkan bahawa Task.Factory.StartNew lalai ke TaskScheduler.Current dan bukan TaskScheduler.Default.

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

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

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

Sekiranya mungkin ingin menggunakan Task.Factory.StartNew jika anda telah membuat penjadual tugas khusus dan menyampaikan contoh penjadual kepadanya secara eksplisit. Saya selalu mengesyorkan menggunakan Task.Run kerana lebih mudah dan mempunyai lalai yang lebih selamat. Dengan kata lain, kita harus mengelakkan penggunaan Task.Factory.StartNew kecuali jika ada keperluan untuk membuat penjadual tugas dan kemudian meneruskannya secara eksplisit ketika memanggil kaedah StartNew untuk membuat tugas baru dan menjadwalkannya. Sekiranya anda menggunakan kaedah TaskFactory.StartNew dengan berkesan dan boleh dipercayai, anda harus menggunakan penjadual tugas khusus dan kemudian tentukan PembatalanToken dan TaskCreationOptions.

Kaedah Task.Run disarankan untuk digunakan apabila anda tidak perlu mempunyai kawalan yang lebih baik terhadap penjadualan benang dan kerumitannya. Anda harus menggunakan Task.Run terutamanya pada kaedah terikat CPU. Walau bagaimanapun, anda harus menggunakan Task.Run semasa menjalankan tugas dan bukan di dalam pelaksanaan tugas. Dengan kata lain, anda harus menggunakan Task.Jalankan bukan dalam pelaksanaan kaedah tetapi pada titik di mana kaedah itu dipanggil. Sebagai contoh, coretan kod berikut adalah contoh sekeping kod "buruk".

public async Task DownloadDataFromWebAsync(Uri uri)

        {

            return await Task.Run(() =>

            {

                using (WebClient webClient = new WebClient())

                {

                    return webClient.DownloadString(uri);

                }

            });

        }

Rujuk coretan kod yang diberikan di atas. Kaedahnya tidak boleh diskalakan kerana akan menyekat utas latar belakang, mengambil utas dari kumpulan utas dan melaksanakannya secara serentak di atasnya. Oleh itu, ia akan menggunakan lebih banyak sumber dalam sistem anda.