Programiranje

Kako zgraditi lasten načrtovalnik opravil v C #

TPL (Task Parallel Library) je ena najzanimivejših novosti v najnovejših različicah .NET Framework, ki je bila prvič predstavljena v .NET Framework 4.0. Za delo s TPL bi morali izkoristiti imenski prostor System.Threading.Tasks.

Kaj so načrtovalci opravil? Zakaj jih potrebujemo?

Kako pa so naloge razporejene? No, obstaja komponenta, imenovana načrtovalnik opravil, ki je odgovorna za razporejanje vaših nalog. V bistvu gre za abstrakcijo za objekt na nizki ravni, ki lahko vaše naloge postavi v niti.

.NET Framework vam ponuja dva načrtovalca opravil. Sem spadajo privzeti načrtovalnik opravil, ki se izvaja v okviru niti .NET framework, in drug načrtovalnik opravil, ki se izvaja v kontekstu sinhronizacije določenega cilja. Upoštevajte, da privzeti načrtovalnik opravil TPL izkorišča področje niti .NET Framework. To področje niti pa predstavlja razred ThreadPool, ki je v imenskem prostoru System.Threading.Tasks.

Čeprav bo privzeti načrtovalnik opravil večino časa zadostoval, boste morda želeli zgraditi lasten načrtovalnik opravil po meri, ki bo zagotavljal dodane funkcionalnosti, tj. Takšne funkcije lahko vključujejo izvajanje FIFO, stopnjo sočasnosti itd.

Razširite razred TaskScheduler v jeziku C #

Za izdelavo lastnega načrtovalnika opravil po meri bi morali ustvariti razred, ki razširja razred System.Threading.Tasks.TaskScheduler. Če želite zgraditi načrtovalnik opravil po meri, morate razširiti abstraktni razred TaskScheduler in preglasiti naslednje metode.

  • QueueTask vrne void in sprejme objekt Task kot parameter in ta metoda se pokliče, ko je naloga načrtovana
  • GetScheduledTasks vrne seznam (natančno IEnumerable) vseh nalog, ki so bile razporejene
  • TryExecuteTaskInline se uporablja za izvajanje nalog v vrstici, tj. Na trenutni niti. V tem primeru se naloge izvršijo, če jih ni treba postaviti v čakalno vrsto

Naslednji delček kode prikazuje, kako lahko razširite razred TaskScheduler, da v C # implementirate svoj načrtovalnik po meri.

javni razred CustomTaskScheduler: TaskScheduler, IDisposable

    {

    }

Kot smo že omenili v tem članku, boste morali v načrtovalniku opravil po meri preglasiti metode GetScheduledTasks, QueueTask in TryExecuteTaskInline.

javni zapečateni razred CustomTaskScheduler: TaskScheduler, IDisposable

  {

zaščitena razveljavitev IEnumerable GetScheduledTasks ()

        {

//NAREDITI

        }

zaščiteno razveljavitev void QueueTask (opravilo opravila)

        {

//NAREDITI

        }

zaščiteno preglasitev bool TryExecuteTaskInline (naloga opravila, naloga boolWasPreviouslyQueued)

        {

//NAREDITI

        }

javna void Dispose ()

        {

//NAREDITI

        }

  }

Uporabite BlockingCollection za shranjevanje zbirke predmetov opravil v C #

Začnimo z izvajanjem našega načrtovalnika opravil po meri. Naslednji delček kode prikazuje, kako lahko izkoristite BlockingCollection za shranjevanje zbirke predmetov opravil.

javni zapečateni razred CustomTaskScheduler: TaskScheduler, IDisposable

 {

private BlockingCollection tasksCollection = novo BlockingCollection ();

zasebno samo za branje Thread mainThread = null;

javni CustomTaskScheduler ()

        {

mainThread = nova nit (nov ThreadStart (Izvedi));

če (! mainThread.IsAlive)

            {

mainThread.Start ();

            }

        }

private void Izvedi ()

        {

foreach (var naloga v taskCollection.GetConsumingEnumerable ())

            {

TryExecuteTask (naloga);

            }

        } 

// Druge metode

  }

Glejte konstruktor razreda CustomTaskScheduler. Upoštevajte, kako je bila ustvarjena nova nit, ki je začela izvajati metodo Execute.

Implementirajte metode GetScheduledTasks, QueueTask in TryExecuteTaskInline v C #

Nato moramo implementirati tri metode, ki jih moramo preglasiti v našem načrtovalniku opravil po meri. Te tri metode vključujejo GetScheduledTasks, QueueTask in TryExecuteTaskInline.

Metoda GetScheduledTasks vrne primerek zbirke opravil kot IEnumerable. To se uporablja, da lahko naštejete zbirko, kot je prikazano v metodi Execute. Metoda QueueTask sprejme objekt Task kot parameter in ga shrani v zbirko opravil. Metoda TryExecuteTaskInline nima izvedbe - bralcu bom prepustil, da jo izvede.

zaščiteno preglasitev IEnumerable GetScheduledTasks ()

        {

vrni taskCollection.ToArray ();

        }

zaščiteno razveljavitev void QueueTask (opravilo opravila)

        {

če (naloga! = null)

taskCollection.Add (naloga);

        }

zaščiteno preglasitev bool TryExecuteTaskInline (naloga opravila, naloga boolWasPreviouslyQueued)

        {

vrni false;

        }

Izpolnite primer CustomTaskScheduler v jeziku C #

Naslednji seznam kod ponazarja končno različico našega CustomTaskScheduler.

javni zapečateni razred CustomTaskScheduler: TaskScheduler, IDisposable

    {

private BlockingCollection tasksCollection = novo BlockingCollection ();

zasebno samo za branje Thread mainThread = null;

javni CustomTaskScheduler ()

        {

mainThread = nova nit (nov ThreadStart (Izvedi));

če (! mainThread.IsAlive)

            {

mainThread.Start ();

            }

        }

private void Izvedi ()

        {

foreach (var naloga v taskCollection.GetConsumingEnumerable ())

            {

TryExecuteTask (naloga);

            }

        }

zaščitena razveljavitev IEnumerable GetScheduledTasks ()

        {

vrni taskCollection.ToArray ();

        }

zaščiteno razveljavitev void QueueTask (opravilo opravila)

        {

če (naloga! = null)

taskCollection.Add (naloga);

        }

zaščiteno preglasitev bool TryExecuteTaskInline (naloga opravila, naloga boolWasPreviouslyQueued)

        {

vrni false;

        }

private void Dispose (odstranjevanje z bool)

        {

če (! odstranjevanje) vrne;

taskCollection.CompleteAdding ();

taskCollection.Dispose ();

        }

javna void Dispose ()

        {

Razpolagati (resnično);

GC.SuppressFinalize (to);

        }

    }

Za uporabo razporejevalnika opravil po meri, ki smo ga pravkar uvedli, lahko uporabite naslednji delček kode:

CustomTaskScheduler taskScheduler = nov CustomTaskScheduler ();

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

Kako narediti več v jeziku C #:

  • Kdaj uporabiti abstraktni razred v primerjavi z vmesnikom v jeziku C #
  • Kako delati z AutoMapper v C #
  • Kako uporabljati lambda izraze v jeziku C #
  • Kako delati z delegati Action, Func in Predicate v C #
  • Kako delati z delegati v C #
  • Kako implementirati preprost zapisovalnik v jeziku C #
  • Kako delati z atributi v jeziku C #
  • Kako delati z log4net v C #
  • Kako implementirati vzorec oblikovanja repozitorija v C #
  • Kako delati z refleksijo v jeziku C #
  • Kako delati z nadzornikom datotek v C #
  • Kako izvesti leno inicializacijo v C #
  • Kako delati z MSM v C #
  • Kako delati z razširitvenimi metodami v jeziku C #
  • Kako do lambda izrazov v jeziku C #
  • Kdaj uporabiti hlapljivo ključno besedo v jeziku C #
  • Kako uporabiti ključno besedo yield v jeziku C #
  • Kako uporabiti polimorfizem v jeziku C #
  • Kako zgraditi lasten načrtovalnik opravil v C #
  • Kako delati z RabbitM v C #
  • Kako delati s korpico v jeziku C #
  • Raziskovanje virtualnih in abstraktnih metod v jeziku C #
$config[zx-auto] not found$config[zx-overlay] not found