Как да изградите свой собствен планировчик на задачи в C #

TPL (Task Parallel Library) е една от най-интересните нови функции в последните версии на .NET framework, като за първи път е въведена в .NET Framework 4.0. За да работите с TPL, ще трябва да се възползвате от пространството от имена System.Threading.Tasks.

Какво представляват планиращите задачи? Защо ни трябват?

Сега как са задачите по график? Е, има компонент, наречен планировчик на задачи, който отговаря за планирането на задачите ви. По същество това е абстракция за обект от ниско ниво, който може да постави задачите ви на опашка в нишки.

.NET Framework ви предоставя два планиращи задачи. Те включват планиращия задача по подразбиране, който се изпълнява в пула от нишки на .NET framework, и друг планировчик на задачи, който се изпълнява в контекста на синхронизация на определена цел. Имайте предвид, че планиращият задачи по подразбиране на TPL се възползва от пула от нишки .NET Framework. Този пул от нишки от своя страна е представен от класа ThreadPool, който се съдържа в пространството от имена System.Threading.Tasks.

Въпреки че планиращият задачи по подразбиране ще е достатъчен през повечето време, може да искате да създадете свой собствен персонален планировчик на задачи, за да осигурите добавени функционалности, т.е. функции, които не се предоставят от планиращия задачи по подразбиране. Такива функции могат да включват, изпълнение на FIFO, степен на съвпадение и т.н.

Разширете класа на TaskScheduler в C #

За да създадете свой собствен график за планиране на задачи, ще трябва да създадете клас, който разширява класа System.Threading.Tasks.TaskScheduler. Така че, за да създадете персонализиран планировчик на задачи, ще трябва да разширите абстрактния клас на TaskScheduler и да замените следните методи.

  • QueueTask връща void и приема обект Task като параметър и този метод се извиква, когато задачата трябва да бъде насрочена
  • GetScheduledTasks връща списък (IEnumerable, за да бъдем точни) на всички задачи, които са планирани
  • TryExecuteTaskInline се използва за изпълнение на задачи вградени, т.е. върху текущата нишка. В този случай задачите се изпълняват, без да е необходимо да се поставят в опашка

Следният кодов фрагмент показва как можете да разширите класа TaskScheduler, за да внедрите вашия персонализиран планировчик в C #.

публичен клас CustomTaskScheduler: TaskScheduler, IDisposable

    {

    }

Както обсъждахме по-рано в тази статия, ще трябва да замените методите GetScheduledTasks, QueueTask и TryExecuteTaskInline в персонализирания планировчик на задачи.

публично запечатан клас CustomTaskScheduler: TaskScheduler, IDisposable

  {

        защитено заместване на IEnumerable GetScheduledTasks ()

        {

            //ДА НАПРАВЯ

        }

        защитена отмяна void QueueTask (задача задача)

        {

             //ДА НАПРАВЯ

        }

        защитена замяна bool TryExecuteTaskInline (Задача на задачата, задача на boolWasPreviouslyQueued)

        {

            //ДА НАПРАВЯ

        }

        публично невалидно разпореждане ()

        {

            //ДА НАПРАВЯ

        }

  }

Използвайте BlockingCollection, за да съхранявате колекция от обекти на задачи в C #

Нека сега започнем да прилагаме нашия персонализиран планировчик на задачи. Следният кодов фрагмент показва как можете да използвате BlockingCollection за съхраняване на колекция от обекти на задачи.

публично запечатан клас CustomTaskScheduler: TaskScheduler, IDisposable

 {

        private BlockingCollection tasksCollection = нов BlockingCollection ();

        частна нишка само за четене mainThread = null;

        публичен CustomTaskScheduler ()

        {

            mainThread = нов Thread (нов ThreadStart (Изпълнение));

            ако (! mainThread.IsAlive)

            {

                mainThread.Start ();

            }

        }

        private void Изпълнение ()

        {

            foreach (var задача в taskCollection.GetConsumingEnumerable ())

            {

                TryExecuteTask (задача);

            }

        } 

      // Други методи

  }

Обърнете се към конструктора на класа CustomTaskScheduler. Обърнете внимание как е създадена нова нишка и е започнало да се изпълнява методът Execute.

Внедрете методите GetScheduledTasks, QueueTask и TryExecuteTaskInline в C #

След това трябва да приложим трите метода, които трябва да заменим в нашия персонализиран планировчик на задачи. Тези три метода включват GetScheduledTasks, QueueTask и TryExecuteTaskInline.

Методът GetScheduledTasks връща екземпляра на колекцията от задачи като IEnumerable. Това се използва, за да можете да изброите колекцията, както е показано в метода Execute. Методът QueueTask приема обект на задача като параметър и го съхранява в колекцията от задачи. Методът TryExecuteTaskInline няма изпълнение - ще оставя на читателя да го внедри.

защитено заместване на IEnumerable GetScheduledTasks ()

        {

            връщане taskCollection.ToArray ();

        }

        защитена отмяна void QueueTask (задача задача)

        {

            ако (задача! = нула)

                taskCollection.Add (задача);

        }

        защитена замяна bool TryExecuteTaskInline (Задача на задачата, задача на boolWasPreviouslyQueued)

        {

            върнете false;

        }

Попълнете примера на CustomTaskScheduler в C #

Следният списък с кодове илюстрира окончателната версия на нашия CustomTaskScheduler.

публично запечатан клас CustomTaskScheduler: TaskScheduler, IDisposable

    {

        private BlockingCollection tasksCollection = нов BlockingCollection ();

        частна нишка само за четене mainThread = null;

        публичен CustomTaskScheduler ()

        {

            mainThread = нов Thread (нов ThreadStart (Изпълнение));

            ако (! mainThread.IsAlive)

            {

                mainThread.Start ();

            }

        }

        private void Изпълнение ()

        {

            foreach (var задача в taskCollection.GetConsumingEnumerable ())

            {

                TryExecuteTask (задача);

            }

        }

        защитено заместване на IEnumerable GetScheduledTasks ()

        {

            връщане taskCollection.ToArray ();

        }

        защитена отмяна void QueueTask (задача задача)

        {

            ако (задача! = нула)

                taskCollection.Add (задача);           

        }

        защитена замяна bool TryExecuteTaskInline (Задача на задачата, задача на boolWasPreviouslyQueued)

        {

            върнете false;

        }

        частна празнина Изхвърляне (изхвърляне на bool)

        {

            if (! dispose) return;

            taskCollection.CompleteAdding ();

            taskCollection.Dispose ();

        }

        публично невалидно разпореждане ()

        {

            Изхвърляне (вярно);

            GC.SuppressFinalize (това);

        }

    }

За да използвате току-що въведения персонализиран планировчик на задачи, можете да използвате следния кодов фрагмент:

CustomTaskScheduler taskScheduler = нов CustomTaskScheduler ();

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

Как да направите повече в C #:

  • Кога да се използва абстрактен клас срещу интерфейс в C #
  • Как да работя с AutoMapper в C #
  • Как да използвам ламбда изрази в C #
  • Как да работя с Action, Func и Predicate делегати в C #
  • Как да работя с делегати в C #
  • Как да внедрите прост регистратор в C #
  • Как да работя с атрибути в C #
  • Как да работя с log4net в C #
  • Как да приложим шаблона за проектиране на хранилището в C #
  • Как да работя с отражение в C #
  • Как да работя с файлова система за наблюдение в C #
  • Как да извършите мързелива инициализация в C #
  • Как да работите с MSM в C #
  • Как да работя с методи за разширение в C #
  • Как да използваме ламбда изрази в C #
  • Кога да се използва летливата ключова дума в C #
  • Как да използвам ключовата дума yield в C #
  • Как да приложим полиморфизъм в C #
  • Как да изградите свой собствен планировчик на задачи в C #
  • Как да работя с RabbitM в C #
  • Как да работите с кортеж в C #
  • Проучване на виртуални и абстрактни методи в C #