Bagaimana membina penjadual tugas anda sendiri di C #

TPL (Task Parallel Library) adalah salah satu ciri baru yang paling menarik dalam versi terbaru .NET framework, yang pertama kali diperkenalkan dalam .NET Framework 4.0. Untuk bekerja dengan TPL, anda perlu memanfaatkan Sistem Nama. Threading.Task ruang nama.

Apa itu penjadual tugas? Mengapa kita memerlukannya?

Sekarang, bagaimana tugas itu dijadualkan? Nah, ada komponen yang disebut task scheduler yang bertanggungjawab untuk menjadwalkan tugas anda. Pada dasarnya, ini adalah abstraksi untuk objek peringkat rendah yang dapat mengantarkan tugas anda ke utas.

Rangka Kerja .NET menyediakan anda dengan dua penjadual tugas. Ini termasuk penjadual tugas lalai yang berjalan di kumpulan utas kerangka .NET, dan penjadual tugas lain yang menjalankan konteks penyegerakan dari sasaran yang ditentukan. Perhatikan bahawa penjadual tugas lalai dari TPL memanfaatkan kumpulan utas .NET Framework. Kumpulan utas ini seterusnya diwakili oleh kelas ThreadPool yang terdapat di dalam Sistem nama. Threading.Tasks names.

Walaupun penjadual tugas lalai akan mencukupi sepanjang waktu, anda mungkin ingin membuat penjadwalan tugas tersuai anda sendiri untuk memberikan fungsi tambahan, yaitu fitur yang tidak disediakan oleh penjadual tugas lalai. Ciri-ciri tersebut mungkin termasuk, pelaksanaan FIFO, tahap persetujuan, dll

Panjangkan kelas TaskScheduler di C #

Untuk membina penjadual tugas khas anda sendiri, anda perlu membuat kelas yang memanjangkan kelas System.Threading.Tasks.TaskScheduler. Oleh itu, untuk membina penjadual tugas khusus, anda perlu memperluas kelas abstrak TaskScheduler dan mengganti kaedah berikut.

  • QueueTask mengembalikan kekosongan dan menerima objek Tugas sebagai parameter dan kaedah ini dipanggil ketika tugas dijadwalkan
  • GetSchedchedTasks mengembalikan senarai (yang dapat dihitung tepat) dari semua tugas yang telah dijadualkan
  • TryExecuteTaskInline digunakan untuk melaksanakan tugas sebaris, iaitu pada utas semasa. Dalam kes ini, tugas-tugas yang dilaksanakan tidak perlu mengantri mereka

Coretan kod berikut menunjukkan bagaimana anda dapat memperluas kelas TaskScheduler untuk menerapkan penjadwalan khusus anda di C #.

kelas awam CustomTaskScheduler: TaskScheduler, IDisposable

    {

    }

Seperti yang telah kita bahas sebelumnya dalam artikel ini, Anda perlu mengganti kaedah GetSchedchedTasks, QueueTask, dan TryExecuteTaskInline dalam penjadwalan tugas tersuai.

kelas tertutup awam CustomTaskScheduler: TaskScheduler, IDisposable

  {

        ganti yang dilindungi IEnumerable GetSchedchedTasks ()

        {

            // TODO

        }

        dilindungi override void QueueTask (Tugas tugas)

        {

             // TODO

        }

        bool override terlindung TryExecuteTaskInline (Tugas tugas, tugas boolWasPre sebelumnyalyQueued)

        {

            // TODO

        }

        kekosongan awam Buang ()

        {

            // TODO

        }

  }

Gunakan BlockingCollection untuk menyimpan koleksi objek tugas di C #

Sekarang mari kita mulai melaksanakan penjadwalan tugas khusus kita. Coretan kod berikut menunjukkan bagaimana anda dapat memanfaatkan BlockingCollection untuk menyimpan koleksi objek tugas.

kelas tertutup awam CustomTaskScheduler: TaskScheduler, IDisposable

 {

        tugas BlockingCollection swastaCollection = BlockingCollection baru ();

        Thread utama baca utama swasta

        CustomTaskScheduler awam ()

        {

            mainThread = Thread baru (ThreadStart baru (Laksanakan));

            jika (! mainThread.IsAlive)

            {

                mainThread.Start ();

            }

        }

        kekosongan peribadi Jalankan ()

        {

            foreach (var tugas dalam taskCollection.GetConsumingEnumerable ())

            {

                TryExecuteTask (tugas);

            }

        } 

      // Kaedah lain

  }

Rujuk kepada pembina kelas CustomTaskScheduler. Perhatikan bagaimana thread baru telah dibuat dan mula menjalankan kaedah Execute.

Terapkan kaedah GetSchedchedTasks, QueueTask, dan TryExecuteTaskInline di C #

Seterusnya, kita perlu menerapkan tiga kaedah yang perlu kita ganti dalam penjadual tugas khusus kita. Ketiga kaedah ini merangkumi GetSchedchedTasks, QueueTask, dan TryExecuteTaskInline.

Kaedah GetSchedchedTasks mengembalikan contoh koleksi tugas sebagai IEnumerable. Ini digunakan supaya anda dapat menghitung koleksi seperti yang ditunjukkan dalam kaedah Jalankan. Kaedah QueueTask menerima objek Task sebagai parameter dan menyimpannya dalam koleksi tugas. Kaedah TryExecuteTaskInline tidak mempunyai pelaksanaan - saya akan menyerahkannya kepada pembaca untuk melaksanakannya.

ganti yang dilindungi IEnumerable GetSchedchedTasks ()

        {

            mengembalikan tugasCollection.ToArray ();

        }

        dilindungi override void QueueTask (Tugas tugas)

        {

            jika (tugas! = batal)

                taskCollection.Add (tugas);

        }

        bool override terlindung TryExecuteTaskInline (Tugas tugas, tugas boolWasPre sebelumnyalyQueued)

        {

            kembali palsu;

        }

Lengkapkan contoh CustomTaskScheduler dalam C #

Penyenaraian kod berikut menggambarkan versi akhir CustomTaskScheduler kami.

kelas tertutup awam CustomTaskScheduler: TaskScheduler, IDisposable

    {

        tugas BlockingCollection swastaCollection = BlockingCollection baru ();

        Thread utama baca utama swasta

        CustomTaskScheduler awam ()

        {

            mainThread = Thread baru (ThreadStart baru (Laksanakan));

            jika (! mainThread.IsAlive)

            {

                mainThread.Start ();

            }

        }

        kekosongan peribadi Jalankan ()

        {

            foreach (var tugas dalam taskCollection.GetConsumingEnumerable ())

            {

                TryExecuteTask (tugas);

            }

        }

        ganti yang dilindungi IEnumerable GetSchedchedTasks ()

        {

            mengembalikan tugasCollection.ToArray ();

        }

        dilindungi override void QueueTask (Tugas tugas)

        {

            jika (tugas! = batal)

                taskCollection.Add (tugas);           

        }

        bool override terlindung TryExecuteTaskInline (Tugas tugas, tugas boolWasPre sebelumnyalyQueued)

        {

            kembali palsu;

        }

        buang peribadi (membuang bool)

        {

            sekiranya (! membuang) kembali;

            taskCollection.CompleteAdding ();

            taskCollection.Dispose ();

        }

        kekosongan awam Buang ()

        {

            Buangkan (benar);

            GC.SuppressFinalize (ini);

        }

    }

Untuk menggunakan penjadual tugas khusus yang baru kami laksanakan, Anda dapat menggunakan potongan kode berikut:

CustomTaskScheduler taskScheduler = CustomTaskScheduler baru ();

Task.Factory.StartNew (() => SomeMethod (), CancellationToken.None, TaskCreationOptions.None, taskScheduler);

Cara melakukan lebih banyak perkara di C #:

  • Bilakah menggunakan kelas abstrak vs antara muka dalam C #
  • Cara bekerja dengan AutoMapper di C #
  • Cara menggunakan ungkapan lambda dalam C #
  • Cara bekerjasama dengan delegasi Action, Func, dan Predicate di C #
  • Cara bekerja dengan perwakilan di C #
  • Cara melaksanakan pembalak sederhana di C #
  • Cara bekerja dengan atribut di C #
  • Cara bekerja dengan log4net di C #
  • Cara melaksanakan corak reka bentuk repositori di C #
  • Cara bekerja dengan refleksi di C #
  • Cara bekerja dengan pemantau sistem fail di C #
  • Cara melakukan inisial malas di C #
  • Cara bekerja dengan MSM di C #
  • Cara bekerja dengan kaedah peluasan di C #
  • Bagaimana untuk kami ungkapan lambda dalam C #
  • Bilakah menggunakan kata kunci tidak stabil dalam C #
  • Cara menggunakan kata kunci hasil dalam C #
  • Cara melaksanakan polimorfisme dalam C #
  • Bagaimana membina penjadual tugas anda sendiri di C #
  • Cara bekerja dengan RabbitM di C #
  • Cara bekerja dengan tuple di C #
  • Meneroka kaedah maya dan abstrak dalam C #