Cara membuat penjadwal tugas Anda sendiri di C #

TPL (Task Parallel Library) adalah salah satu fitur baru yang paling menarik dalam versi terbaru kerangka .NET, yang pertama kali diperkenalkan di .NET Framework 4.0. Untuk bekerja dengan TPL, Anda perlu memanfaatkan namespace System.Threading.Tasks.

Apa itu penjadwal tugas? mengapa kita membutuhkan mereka?

Sekarang, bagaimana tugas tersebut dijadwalkan? Nah, ada komponen yang disebut penjadwal tugas yang bertanggung jawab untuk menjadwalkan tugas Anda. Intinya, ini adalah abstraksi untuk objek tingkat rendah yang dapat memasukkan tugas Anda ke dalam antrean.

.NETFramework memberi Anda dua penjadwal tugas. Ini termasuk penjadwal tugas default yang berjalan di kumpulan benang kerangka .NET, dan penjadwal tugas lain yang mengeksekusi pada konteks sinkronisasi dari target yang ditentukan. Perhatikan bahwa penjadwal tugas default TPL memanfaatkan kumpulan benang .NET Framework. Kumpulan utas ini pada gilirannya diwakili oleh kelas ThreadPool yang terkandung di dalam namespace System.Threading.Tasks.

Meskipun penjadwal tugas default akan mencukupi sebagian besar waktu, Anda mungkin ingin membuat penjadwal tugas kustom Anda sendiri untuk menyediakan fungsionalitas tambahan, yaitu fitur yang tidak disediakan oleh penjadwal tugas default. Fitur tersebut mungkin termasuk, eksekusi FIFO, derajat konkurensi, dll.

Perluas kelas TaskScheduler di C #

Untuk membuat penjadwal tugas kustom Anda sendiri, Anda perlu membuat kelas yang memperluas kelas System.Threading.Tasks.TaskScheduler. Jadi, untuk membuat penjadwal tugas khusus, Anda perlu memperluas kelas abstrak TaskScheduler dan mengganti metode berikut.

  • QueueTask mengembalikan kekosongan dan menerima objek Tugas sebagai parameter dan metode ini dipanggil saat tugas dijadwalkan
  • GetScheduledTasks mengembalikan daftar (tepatnya IEnumerable) dari semua tugas yang telah dijadwalkan
  • TryExecuteTaskInline digunakan untuk menjalankan tugas secara inline, misalnya, pada utas saat ini. Dalam hal ini, tugas-tugas dijalankan tanpa perlu mengantri

Cuplikan kode berikut menunjukkan bagaimana Anda dapat memperluas kelas TaskScheduler untuk mengimplementasikan penjadwal khusus Anda di C #.

kelas publik CustomTaskScheduler: TaskScheduler, IDisposable

    {

    }

Seperti yang telah kita bahas sebelumnya di artikel ini, Anda perlu mengganti metode GetScheduledTasks, QueueTask, dan TryExecuteTaskInline di penjadwal tugas khusus.

kelas tertutup publik CustomTaskScheduler: TaskScheduler, IDisposable

  {

        dilindungi override IEnumerable GetScheduledTasks ()

        {

            //MELAKUKAN

        }

        dilindungi override void QueueTask (Tugas tugas)

        {

             //MELAKUKAN

        }

        dilindungi override bool TryExecuteTaskInline (Tugas tugas, tugas boolWasPreviouslyQueued)

        {

            //MELAKUKAN

        }

        public void Buang ()

        {

            //MELAKUKAN

        }

  }

Gunakan BlockingCollection untuk menyimpan kumpulan objek tugas di C #

Sekarang mari mulai menerapkan penjadwal tugas khusus kita. Cuplikan kode berikut menunjukkan bagaimana Anda dapat memanfaatkan BlockingCollection untuk menyimpan sekumpulan objek tugas.

kelas tertutup publik CustomTaskScheduler: TaskScheduler, IDisposable

 {

        private BlockingCollection taskCollection = new BlockingCollection ();

        pribadi hanya baca Thread mainThread = null;

        public CustomTaskScheduler ()

        {

            mainThread = Thread baru (new ThreadStart (Execute));

            if (! mainThread.IsAlive)

            {

                mainThread.Start ();

            }

        }

        private void Execute ()

        {

            foreach (tugas var di taskCollection.GetConsumingEnumerable ())

            {

                TryExecuteTask (tugas);

            }

        } 

      // Metode lain

  }

Lihat konstruktor kelas CustomTaskScheduler. Perhatikan bagaimana thread baru dibuat dan mulai menjalankan metode Execute.

Implementasikan metode GetScheduledTasks, QueueTask, dan TryExecuteTaskInline di C #

Selanjutnya, kita perlu menerapkan tiga metode yang perlu kita ganti di penjadwal tugas khusus kita. Ketiga metode ini termasuk GetScheduledTasks, QueueTask, dan TryExecuteTaskInline.

Metode GetScheduledTasks mengembalikan contoh kumpulan tugas sebagai IEnumerable. Ini digunakan agar Anda dapat menghitung koleksi seperti yang diperlihatkan dalam metode Jalankan. Metode QueueTask menerima objek Tugas sebagai parameter dan menyimpannya dalam kumpulan tugas. Metode TryExecuteTaskInline tidak memiliki implementasi - Saya akan menyerahkannya kepada pembaca untuk mengimplementasikannya.

dilindungi override IEnumerable GetScheduledTasks ()

        {

            return taskCollection.ToArray ();

        }

        dilindungi override void QueueTask (Tugas tugas)

        {

            if (tugas! = null)

                taskCollection.Add (task);

        }

        dilindungi override bool TryExecuteTaskInline (Tugas tugas, tugas boolWasPreviouslyQueued)

        {

            return false;

        }

Lengkapi contoh CustomTaskScheduler di C #

Daftar kode berikut menggambarkan versi terakhir dari CustomTaskScheduler kami.

kelas tertutup publik CustomTaskScheduler: TaskScheduler, IDisposable

    {

        private BlockingCollection taskCollection = new BlockingCollection ();

        pribadi hanya baca Thread mainThread = null;

        public CustomTaskScheduler ()

        {

            mainThread = Thread baru (new ThreadStart (Execute));

            if (! mainThread.IsAlive)

            {

                mainThread.Start ();

            }

        }

        private void Execute ()

        {

            foreach (tugas var di taskCollection.GetConsumingEnumerable ())

            {

                TryExecuteTask (tugas);

            }

        }

        dilindungi override IEnumerable GetScheduledTasks ()

        {

            return taskCollection.ToArray ();

        }

        dilindungi override void QueueTask (Tugas tugas)

        {

            if (tugas! = null)

                taskCollection.Add (task);           

        }

        dilindungi override bool TryExecuteTaskInline (Tugas tugas, tugas boolWasPreviouslyQueued)

        {

            return false;

        }

        private void Buang (bool disposing)

        {

            if (! disposing) return;

            taskCollection.CompleteAdding ();

            taskCollection.Dispose ();

        }

        public void Buang ()

        {

            Buang (benar);

            GC.SuppressFinalize (ini);

        }

    }

Untuk menggunakan penjadwal tugas khusus yang baru saja kami terapkan, Anda dapat menggunakan cuplikan kode berikut:

CustomTaskScheduler taskScheduler = CustomTaskScheduler baru ();

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

Bagaimana melakukan lebih banyak di C #:

  • Kapan menggunakan kelas abstrak vs. antarmuka di C #
  • Bagaimana bekerja dengan AutoMapper di C #
  • Cara menggunakan ekspresi lambda di C #
  • Cara bekerja dengan delegasi Action, Func, dan Predicate di C #
  • Bagaimana bekerja dengan delegasi di C #
  • Bagaimana menerapkan logger sederhana di C #
  • Bagaimana bekerja dengan atribut di C #
  • Bagaimana bekerja dengan log4net di C #
  • Bagaimana menerapkan pola desain repositori di C #
  • Bagaimana bekerja dengan refleksi di C #
  • Bagaimana bekerja dengan filesystemwatcher di C #
  • Bagaimana melakukan inisialisasi malas di C #
  • Bagaimana bekerja dengan MSM di C #
  • Bagaimana bekerja dengan metode ekstensi di C #
  • Bagaimana kami ekspresi lambda di C #
  • Kapan menggunakan kata kunci volatile di C #
  • Cara menggunakan kata kunci hasil di C #
  • Bagaimana menerapkan polimorfisme di C #
  • Cara membuat penjadwal tugas Anda sendiri di C #
  • Bagaimana bekerja dengan RabbitM di C #
  • Bagaimana bekerja dengan tupel di C #
  • Menjelajahi metode virtual dan abstrak di C #