Programmering

Hvordan lage din egen oppgaveplanlegger i C #

TPL (Task Parallel Library) er en av de mest interessante nye funksjonene i de nyeste versjonene av .NET framework, etter å ha blitt introdusert i .NET Framework 4.0. For å jobbe med TPL må du dra nytte av navneområdet System.Threading.Tasks.

Hva er oppgaveplanleggere? Hvorfor trenger vi dem?

Nå, hvordan er det at oppgavene er planlagt? Vel, det er en komponent som heter oppgaveplanlegger som er ansvarlig for planlegging av oppgavene dine. I det vesentlige er det en abstraksjon for et objekt på lavt nivå som kan stille oppgavene dine i kø.

.NET Framework gir deg to oppgaveplanleggere. Disse inkluderer standard oppgaveplanlegger som kjører på .NET framework thread thread pool, og en annen oppgaveplanlegger som kjøres på synkroniseringskonteksten til et spesifisert mål. Merk at standard oppgaveplanlegger for TPL benytter seg av .NET Framework-trådgruppen. Denne trådgruppen er i sin tur representert av ThreadPool-klassen som er inneholdt i System.Threading.Tasks namespace.

Selv om standard oppgaveplanlegger vil være tilstrekkelig mesteparten av tiden, kan det være lurt å bygge din egen egendefinerte oppgaveplanlegger for å gi ekstra funksjoner, dvs. funksjoner som ikke er levert av standard oppgaveplanlegger. Slike funksjoner kan omfatte FIFO-utførelse, grad av samtidighet, etc.

Utvid TaskScheduler-klassen i C #

For å bygge din egen tilpassede oppgaveplanlegger, må du opprette en klasse som utvider System.Threading.Tasks.TaskScheduler-klassen. Så for å bygge en tilpasset oppgaveplanlegger, må du utvide TaskScheduler-abstraktklassen og overstyre følgende metoder.

  • QueueTask returnerer ugyldig og godtar et oppgaveobjekt som parameter, og denne metoden kalles når en oppgave skal planlegges
  • GetScheduledTasks returnerer en liste (en IEnumrerbar for å være presis) over alle oppgavene som er planlagt
  • TryExecuteTaskInline brukes til å utføre oppgaver innebygd, dvs. på den gjeldende tråden. I dette tilfellet utføres oppgavene uten behov for å stille dem i kø

Følgende kodebit viser hvordan du kan utvide TaskScheduler-klassen for å implementere den tilpassede planleggeren i C #.

offentlig klasse CustomTaskScheduler: TaskScheduler, IDisposable

    {

    }

Som vi diskuterte tidligere i denne artikkelen, må du overstyre metodene GetScheduledTasks, QueueTask og TryExecuteTaskInline i den egendefinerte oppgaveplanleggeren.

offentlig forseglet klasse CustomTaskScheduler: TaskScheduler, IDisposable

  {

beskyttet overstyring IEnumerable GetScheduledTasks ()

        {

//Å GJØRE

        }

beskyttet overstyring ugyldig QueueTask (oppgaveoppgave)

        {

//Å GJØRE

        }

beskyttet overstyringsbool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)

        {

//Å GJØRE

        }

offentlig tomrom Kast ()

        {

//Å GJØRE

        }

  }

Bruk BlockingCollection til å lagre en samling oppgaveobjekter i C #

La oss nå begynne å implementere vår tilpassede oppgaveplanlegger. Følgende kodebit viser hvordan du kan utnytte BlockingCollection til å lagre en samling oppgaveobjekter.

offentlig forseglet klasse CustomTaskScheduler: TaskScheduler, IDisposable

 {

private BlockingCollection-oppgaverCollection = ny BlockingCollection ();

private readonly Tråd mainThread = null;

offentlig CustomTaskScheduler ()

        {

mainThread = ny tråd (ny trådstart (utfør));

hvis (! mainThread.IsAlive)

            {

mainThread.Start ();

            }

        }

privat tomrom Utfør ()

        {

foreach (var oppgave i TasksCollection.GetConsumingEnumerable ())

            {

TryExecuteTask (oppgave);

            }

        } 

// Andre metoder

  }

Henvis til konstruktøren til klassen CustomTaskScheduler. Legg merke til hvordan en ny tråd er opprettet og startet for å kjøre Execute-metoden.

Implementere metodene GetScheduledTasks, QueueTask og TryExecuteTaskInline i C #

Deretter må vi implementere de tre metodene som vi trenger å overstyre i vår tilpassede oppgaveplanlegger. Disse tre metodene inkluderer GetScheduledTasks, QueueTask og TryExecuteTaskInline.

GetScheduledTasks-metoden returnerer forekomsten av oppgavesamlingen som IEnumerable. Dette brukes slik at du kan telle opp samlingen som vist i Execute-metoden. QueueTask-metoden godtar et oppgaveobjekt som en parameter og lagrer det i oppgavesamlingen. TryExecuteTaskInline-metoden har ingen implementering - jeg overlater til leseren å implementere den.

beskyttet overstyring IEnumerable GetScheduledTasks ()

        {

returner oppgaverCollection.ToArray ();

        }

beskyttet overstyring ugyldig QueueTask (oppgaveoppgave)

        {

hvis (oppgave! = null)

TasksCollection.Add (oppgave);

        }

beskyttet overstyringsbool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)

        {

returner falsk;

        }

Komplett CustomTaskScheduler-eksempel i C #

Følgende kodeliste illustrerer den endelige versjonen av vår CustomTaskScheduler.

offentlig forseglet klasse CustomTaskScheduler: TaskScheduler, IDisposable

    {

private BlockingCollection-oppgaverCollection = ny BlockingCollection ();

privat readonly Tråd mainThread = null;

offentlig CustomTaskScheduler ()

        {

mainThread = ny tråd (ny trådstart (utfør));

hvis (! mainThread.IsAlive)

            {

mainThread.Start ();

            }

        }

privat tomrom Utfør ()

        {

foreach (var task in TasksCollection.GetConsumingEnumerable ())

            {

TryExecuteTask (oppgave);

            }

        }

beskyttet overstyring IEnumerable GetScheduledTasks ()

        {

returner oppgaverCollection.ToArray ();

        }

beskyttet overstyring ugyldig QueueTask (oppgaveoppgave)

        {

hvis (oppgave! = null)

TasksCollection.Add (oppgave);

        }

beskyttet overstyringsbool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)

        {

returner falsk;

        }

privat tomrom Kast (bool disponere)

        {

hvis (! disponere) retur;

TasksCollection.CompleteAdding ();

TasksCollection.Dispose ();

        }

offentlig tomrom Kast ()

        {

Kast (sann);

GC.SuppressFinalize (dette);

        }

    }

For å bruke den tilpassede oppgaveplanleggeren vi nettopp implementerte, kan du bruke følgende kodebit:

CustomTaskScheduler taskScheduler = ny CustomTaskScheduler ();

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

Hvordan gjøre mer i C #:

  • Når skal jeg bruke en abstrakt klasse vs. grensesnitt i C #
  • Hvordan jobbe med AutoMapper i C #
  • Hvordan bruke lambdauttrykk i C #
  • Hvordan jobbe med Action-, Func- og Predicate-delegater i C #
  • Hvordan jobbe med delegater i C #
  • Slik implementerer du en enkel logger i C #
  • Hvordan jobbe med attributter i C #
  • Hvordan jobbe med log4net i C #
  • Slik implementerer du mønsteret for depotdesign i C #
  • Hvordan jobbe med refleksjon i C #
  • Hvordan jobbe med filsystemwatcher i C #
  • Hvordan utføre lat initialisering i C #
  • Hvordan jobbe med MSM i C #
  • Hvordan jobbe med utvidelsesmetoder i C #
  • Hvordan vi lambdauttrykk i C #
  • Når skal du bruke det flyktige nøkkelordet i C #
  • Slik bruker du avkastningsnøkkelordet i C #
  • Hvordan implementere polymorfisme i C #
  • Hvordan lage din egen oppgaveplanlegger i C #
  • Hvordan jobbe med RabbitM i C #
  • Hvordan jobbe med en tuple i C #
  • Utforske virtuelle og abstrakte metoder i C #
$config[zx-auto] not found$config[zx-overlay] not found