So erstellen Sie Ihren eigenen Taskplaner in C #

Die TPL (Task Parallel Library) ist eine der interessantesten neuen Funktionen in den neuesten Versionen von .NET Framework, die erstmals in .NET Framework 4.0 eingeführt wurden. Um mit der TPL arbeiten zu können, müssten Sie den Namespace System.Threading.Tasks nutzen.

Was sind Taskplaner? Warum brauchen wir sie?

Wie sind die Aufgaben geplant? Nun, es gibt eine Komponente namens Task Scheduler, die für die Planung Ihrer Aufgaben verantwortlich ist. Im Wesentlichen handelt es sich um eine Abstraktion für ein Objekt auf niedriger Ebene, das Ihre Aufgaben in Threads einreihen kann.

Das .NET Framework bietet Ihnen zwei Taskplaner. Dazu gehören der Standard-Taskplaner, der im Thread-Pool von .NET Framework ausgeführt wird, und ein weiterer Taskplaner, der im Synchronisationskontext eines angegebenen Ziels ausgeführt wird. Beachten Sie, dass der Standard-Taskplaner der TPL den .NET Framework-Thread-Pool nutzt. Dieser Thread-Pool wird wiederum durch die ThreadPool-Klasse dargestellt, die im System.Threading.Tasks-Namespace enthalten ist.

Obwohl der Standard-Taskplaner die meiste Zeit ausreicht, möchten Sie möglicherweise einen eigenen benutzerdefinierten Taskplaner erstellen, um zusätzliche Funktionen bereitzustellen, dh Funktionen, die vom Standard-Taskplaner nicht bereitgestellt werden. Solche Merkmale können FIFO-Ausführung, Grad der Parallelität usw. umfassen.

Erweitern Sie die TaskScheduler-Klasse in C #

Um Ihren eigenen benutzerdefinierten Taskplaner zu erstellen, müssen Sie eine Klasse erstellen, die die System.Threading.Tasks.TaskScheduler-Klasse erweitert. Um einen benutzerdefinierten Taskplaner zu erstellen, müssen Sie die abstrakte TaskScheduler-Klasse erweitern und die folgenden Methoden überschreiben.

  • QueueTask gibt void zurück und akzeptiert ein Task-Objekt als Parameter. Diese Methode wird aufgerufen, wenn eine Task geplant werden soll
  • GetScheduledTasks gibt eine Liste (genauer gesagt eine IEnumerable) aller geplanten Aufgaben zurück
  • TryExecuteTaskInline wird verwendet, um Aufgaben inline auszuführen, dh im aktuellen Thread. In diesem Fall werden die Aufgaben ausgeführt, ohne dass sie in die Warteschlange gestellt werden müssen

Das folgende Codeausschnitt zeigt, wie Sie die TaskScheduler-Klasse erweitern können, um Ihren benutzerdefinierten Scheduler in C # zu implementieren.

öffentliche Klasse CustomTaskScheduler: TaskScheduler, IDisposable

    {

    }}

Wie bereits weiter oben in diesem Artikel erläutert, müssen Sie die Methoden GetScheduledTasks, QueueTask und TryExecuteTaskInline im benutzerdefinierten Taskplaner überschreiben.

öffentliche versiegelte Klasse CustomTaskScheduler: TaskScheduler, IDisposable

  {

        geschützte Überschreibung IEnumerable GetScheduledTasks ()

        {

            //MACHEN

        }}

        geschützte Überschreibung void QueueTask (Task task)

        {

             //MACHEN

        }}

        geschützte Überschreibung bool TryExecuteTaskInline (Task task, bool taskWasPreviousQueued)

        {

            //MACHEN

        }}

        public void Dispose ()

        {

            //MACHEN

        }}

  }}

Verwenden Sie BlockingCollection, um eine Sammlung von Aufgabenobjekten in C # zu speichern

Beginnen wir jetzt mit der Implementierung unseres benutzerdefinierten Aufgabenplaners. Das folgende Codeausschnitt zeigt, wie Sie BlockingCollection nutzen können, um eine Sammlung von Aufgabenobjekten zu speichern.

öffentliche versiegelte Klasse CustomTaskScheduler: TaskScheduler, IDisposable

 {

        private BlockingCollection taskCollection = new BlockingCollection ();

        privat schreibgeschützt Thread mainThread = null;

        public CustomTaskScheduler ()

        {

            mainThread = neuer Thread (neuer ThreadStart (Execute));

            if (! mainThread.IsAlive)

            {

                mainThread.Start ();

            }}

        }}

        private void Execute ()

        {

            foreach (var task in taskCollection.GetConsumingEnumerable ())

            {

                TryExecuteTask (Aufgabe);

            }}

        }} 

      //Andere Methoden

  }}

Beziehen Sie sich auf den Konstruktor der CustomTaskScheduler-Klasse. Beachten Sie, wie ein neuer Thread erstellt und gestartet wurde, um die Execute-Methode auszuführen.

Implementieren Sie die Methoden GetScheduledTasks, QueueTask und TryExecuteTaskInline in C #

Als Nächstes müssen wir die drei Methoden implementieren, die wir in unserem benutzerdefinierten Taskplaner überschreiben müssen. Diese drei Methoden umfassen GetScheduledTasks, QueueTask und TryExecuteTaskInline.

Die GetScheduledTasks-Methode gibt die Instanz der Task-Auflistung als IEnumerable zurück. Dies wird verwendet, damit Sie die Auflistung wie in der Execute-Methode gezeigt auflisten können. Die QueueTask-Methode akzeptiert ein Task-Objekt als Parameter und speichert es in der Task-Auflistung. Die TryExecuteTaskInline-Methode hat keine Implementierung - ich überlasse es dem Leser, sie zu implementieren.

geschützte Überschreibung IEnumerable GetScheduledTasks ()

        {

            return taskCollection.ToArray ();

        }}

        geschützte Überschreibung void QueueTask (Task task)

        {

            if (task! = null)

                taskCollection.Add (Aufgabe);

        }}

        geschützte Überschreibung bool TryExecuteTaskInline (Task task, bool taskWasPreviousQueued)

        {

            falsch zurückgeben;

        }}

Vollständiges CustomTaskScheduler-Beispiel in C #

Die folgende Codeliste zeigt die endgültige Version unseres CustomTaskScheduler.

öffentliche versiegelte Klasse CustomTaskScheduler: TaskScheduler, IDisposable

    {

        private BlockingCollection taskCollection = new BlockingCollection ();

        privat schreibgeschützt Thread mainThread = null;

        public CustomTaskScheduler ()

        {

            mainThread = neuer Thread (neuer ThreadStart (Execute));

            if (! mainThread.IsAlive)

            {

                mainThread.Start ();

            }}

        }}

        private void Execute ()

        {

            foreach (var task in taskCollection.GetConsumingEnumerable ())

            {

                TryExecuteTask (Aufgabe);

            }}

        }}

        geschützte Überschreibung IEnumerable GetScheduledTasks ()

        {

            return taskCollection.ToArray ();

        }}

        geschützte Überschreibung void QueueTask (Task task)

        {

            if (task! = null)

                taskCollection.Add (Aufgabe);           

        }}

        geschützte Überschreibung bool TryExecuteTaskInline (Task task, bool taskWasPreviousQueued)

        {

            falsch zurückgeben;

        }}

        private void Dispose (bool disposing)

        {

            wenn (! entsorgen) zurückkehren;

            taskCollection.CompleteAdding ();

            taskCollection.Dispose ();

        }}

        public void Dispose ()

        {

            Entsorgen (wahr);

            GC.SuppressFinalize (this);

        }}

    }}

Um den soeben implementierten benutzerdefinierten Taskplaner zu verwenden, können Sie das folgende Codefragment verwenden:

CustomTaskScheduler taskScheduler = new CustomTaskScheduler ();

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

So machen Sie mehr in C #:

  • Wann wird eine abstrakte Klasse im Vergleich zur Schnittstelle in C # verwendet?
  • So arbeiten Sie mit AutoMapper in C #
  • Verwendung von Lambda-Ausdrücken in C #
  • So arbeiten Sie mit Action-, Func- und Predicate-Delegaten in C #
  • So arbeiten Sie mit Delegierten in C #
  • So implementieren Sie einen einfachen Logger in C #
  • So arbeiten Sie mit Attributen in C #
  • So arbeiten Sie mit log4net in C #
  • So implementieren Sie das Repository-Entwurfsmuster in C #
  • Wie man mit Reflexion in C # arbeitet
  • So arbeiten Sie mit dem Dateisystemwatcher in C #
  • So führen Sie eine verzögerte Initialisierung in C # durch
  • So arbeiten Sie mit MSM in C #
  • So arbeiten Sie mit Erweiterungsmethoden in C #
  • Wie wir Lambda-Ausdrücke in C #
  • Wann wird das flüchtige Schlüsselwort in C # verwendet?
  • Verwendung des Schlüsselwortsield in C #
  • So implementieren Sie Polymorphismus in C #
  • So erstellen Sie Ihren eigenen Taskplaner in C #
  • Wie man mit RabbitM in C # arbeitet
  • So arbeiten Sie mit einem Tupel in C #
  • Erkundung virtueller und abstrakter Methoden in C #