Programmering

Sådan bygger du din egen opgaveplanlægning i C #

TPL (Task Parallel Library) er en af ​​de mest interessante nye funktioner i de nyere versioner af .NET framework, der først blev introduceret i .NET Framework 4.0. For at arbejde med TPL skal du udnytte navneområdet System.Threading.Tasks.

Hvad er opgaveplanlægning? Hvorfor har vi brug for dem?

Hvordan er det nu, at opgaverne er planlagt? Der er en komponent kaldet task scheduler, der er ansvarlig for planlægning af dine opgaver. I det væsentlige er det en abstraktion for et objekt på lavt niveau, der kan sætte dine opgaver i kø i tråde.

.NET Framework giver dig to opgaveplanlægninger. Disse inkluderer standardopgaveplanlægning, der kører på .NET framework-trådpuljen, og en anden opgaveplanlægning, der udføres på synkroniseringskonteksten for et bestemt mål. Bemærk, at TPL's standardopgaveplanlægger udnytter trådpuljen .NET Framework. Denne trådpulje er til gengæld repræsenteret af ThreadPool-klassen, der er indeholdt i System.Threading.Tasks navneområdet.

Selvom standardopgaveplanlæggeren vil være tilstrækkelig det meste af tiden, vil du muligvis opbygge din egen brugerdefinerede opgaveplanlægning for at give tilføjede funktioner, dvs. funktioner, der ikke leveres af standardopgaveplanlæggeren. Sådanne funktioner kan omfatte FIFO-udførelse, grad af samtidighed osv.

Udvid TaskScheduler-klassen i C #

For at oprette din egen tilpassede opgaveplanlægning skal du oprette en klasse, der udvider klassen System.Threading.Tasks.TaskScheduler. Så for at opbygge en brugerdefineret opgaveplanlægning skal du udvide TaskScheduler-abstraktklassen og tilsidesætte følgende metoder.

  • QueueTask returnerer ugyldig og accepterer et Task-objekt som parameter, og denne metode kaldes, når en opgave skal planlægges
  • GetScheduledTasks returnerer en liste (en IEnumrerbar for at være præcis) over alle de opgaver, der er planlagt
  • TryExecuteTaskInline bruges til at udføre opgaver inline, dvs. på den aktuelle tråd. I dette tilfælde udføres opgaverne uden behov for kø i kø

Følgende kodestykke viser, hvordan du kan udvide klassen TaskScheduler til at implementere din brugerdefinerede planlægning i C #.

offentlig klasse CustomTaskScheduler: TaskScheduler, IDisposable

    {

    }

Som vi diskuterede tidligere i denne artikel, skal du tilsidesætte metoderne GetScheduledTasks, QueueTask og TryExecuteTaskInline i den brugerdefinerede opgaveplanlægning.

offentlig forseglet klasse CustomTaskScheduler: TaskScheduler, IDisposable

  {

beskyttet tilsidesættelse IEnumerable GetScheduledTasks ()

        {

//AT GØRE

        }

beskyttet tilsidesættelse ugyldig QueueTask (opgaveopgave)

        {

//AT GØRE

        }

beskyttet tilsidesættelse bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)

        {

//AT GØRE

        }

offentlig tomrum Bortskaff ()

        {

//AT GØRE

        }

  }

Brug BlockingCollection til at gemme en samling af opgaveobjekter i C #

Lad os nu begynde at implementere vores tilpassede opgaveplanlægning. Følgende kodestykke viser, hvordan du kan udnytte BlockingCollection til at gemme en samling af opgaveobjekter.

offentlig forseglet klasse CustomTaskScheduler: TaskScheduler, IDisposable

 {

private BlockingCollection-opgaverCollection = ny BlockingCollection ();

privat readonly tråd mainThread = null;

offentlig CustomTaskScheduler ()

        {

mainThread = ny tråd (ny trådStart (udfør));

hvis (! mainThread.IsAlive)

            {

mainThread.Start ();

            }

        }

privat tomrum Udfør ()

        {

foreach (var opgave i TasksCollection.GetConsumingEnumerable ())

            {

TryExecuteTask (opgave);

            }

        } 

// Andre metoder

  }

Se konstruktøren til klassen CustomTaskScheduler. Bemærk hvordan en ny tråd er oprettet og startet til at køre metoden Udfør.

Implementere GetScheduledTasks, QueueTask og TryExecuteTaskInline metoder i C #

Dernæst skal vi implementere de tre metoder, som vi har brug for at tilsidesætte i vores brugerdefinerede opgaveplanlægning. Disse tre metoder inkluderer GetScheduledTasks, QueueTask og TryExecuteTaskInline.

Metoden GetScheduledTasks returnerer forekomsten af ​​opgaveindsamlingen som IEnumerable. Dette bruges, så du kan tælle samlingen som vist i metoden Udfør. Metoden QueueTask accepterer et Task-objekt som en parameter og gemmer det i opgavesamlingen. TryExecuteTaskInline-metoden har ingen implementering - jeg overlader det til læseren at implementere den.

beskyttet tilsidesættelse IEnumerable GetScheduledTasks ()

        {

returnere opgaverCollection.ToArray ();

        }

beskyttet tilsidesættelse ugyldig QueueTask (opgaveopgave)

        {

hvis (opgave! = null)

taskCollection.Add (opgave);

        }

beskyttet tilsidesættelse bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)

        {

returner falsk;

        }

Komplet CustomTaskScheduler-eksempel i C #

Følgende kodeliste illustrerer den endelige version af vores CustomTaskScheduler.

offentlig forseglet klasse CustomTaskScheduler: TaskScheduler, IDisposable

    {

private BlockingCollection-opgaverCollection = ny BlockingCollection ();

privat readonly tråd mainThread = null;

offentlig CustomTaskScheduler ()

        {

mainThread = ny tråd (ny trådStart (udfør));

hvis (! mainThread.IsAlive)

            {

mainThread.Start ();

            }

        }

privat tomrum Udfør ()

        {

foreach (var opgave i TasksCollection.GetConsumingEnumerable ())

            {

TryExecuteTask (opgave);

            }

        }

beskyttet tilsidesættelse IEnumerable GetScheduledTasks ()

        {

returnere opgaverCollection.ToArray ();

        }

beskyttet tilsidesættelse ugyldig QueueTask (opgaveopgave)

        {

hvis (opgave! = null)

taskCollection.Add (opgave);

        }

beskyttet tilsidesættelse bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)

        {

returner falsk;

        }

privat tomrum Bortskaffelse (bool bortskaffelse)

        {

hvis (! bortskaffende) retur;

tasksCollection.CompleteAdding ();

opgaverCollection.Dispose ();

        }

offentlig tomrum Bortskaff ()

        {

Bortskaf (sandt);

GC.SuppressFinalize (dette);

        }

    }

For at bruge den brugerdefinerede opgaveplanlægning, vi lige har implementeret, kan du bruge følgende kodestykke:

CustomTaskScheduler taskScheduler = ny CustomTaskScheduler ();

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

Sådan gør du mere i C #:

  • Hvornår skal man bruge en abstrakt klasse vs. interface i C #
  • Sådan arbejder du med AutoMapper i C #
  • Sådan bruges lambda-udtryk i C #
  • Sådan arbejder du med Action-, Func- og Predicate-delegerede i C #
  • Sådan arbejder du med delegerede i C #
  • Sådan implementeres en simpel logger i C #
  • Sådan arbejder du med attributter i C #
  • Sådan arbejder du med log4net i C #
  • Sådan implementeres depotdesignmønsteret i C #
  • Sådan arbejder du med refleksion i C #
  • Sådan arbejder du med filsystemwatcher i C #
  • Sådan udføres doven initialisering i C #
  • Sådan arbejder du med MSM i C #
  • Sådan arbejder du med udvidelsesmetoder i C #
  • Hvordan vi lambda-udtryk i C #
  • Hvornår skal du bruge det flygtige nøgleord i C #
  • Sådan bruges afkastnøgleordet i C #
  • Sådan implementeres polymorfisme i C #
  • Sådan bygger du din egen opgaveplanlægning i C #
  • Sådan arbejder du med RabbitM i C #
  • Sådan arbejder du med en tuple i C #
  • Udforskning af virtuelle og abstrakte metoder i C #