Programování

Jak vytvořit svůj vlastní plánovač úloh v C #

TPL (Task Parallel Library) je jednou z nejzajímavějších nových funkcí v posledních verzích .NET framework, která byla poprvé představena v .NET Framework 4.0. Chcete-li pracovat s TPL, budete muset využít výhody oboru názvů System.Threading.Tasks.

Co jsou plánovače úkolů? Proč je potřebujeme?

Jak je naplánováno plnění úkolů? K dispozici je komponenta zvaná plánovač úloh, která je zodpovědná za plánování vašich úkolů. V podstatě jde o abstrakci pro objekt nízké úrovně, který může zařadit vaše úkoly do fronty na vlákna.

.NET Framework vám poskytuje dva plánovače úloh. Patří mezi ně výchozí plánovač úloh, který běží na fondu podprocesů .NET Framework, a další plánovač úloh, který se spouští v kontextu synchronizace zadaného cíle. Všimněte si, že výchozí plánovač úloh TPL využívá fond podprocesů .NET Framework. Tento fond vláken je zase reprezentován třídou ThreadPool, která je obsažena uvnitř oboru názvů System.Threading.Tasks.

Ačkoli výchozí plánovač úloh bude většinu času stačit, možná budete chtít vytvořit svůj vlastní vlastní plánovač úloh, který bude poskytovat přidané funkce, tj. Funkce, které výchozí plánovač úloh neposkytuje. Mezi takové funkce může patřit provádění FIFO, stupeň souběžnosti atd.

Rozšířit třídu TaskScheduler v C #

Chcete-li vytvořit svůj vlastní vlastní plánovač úloh, budete muset vytvořit třídu, která rozšiřuje třídu System.Threading.Tasks.TaskScheduler. Chcete-li tedy vytvořit vlastní plánovač úloh, budete muset rozšířit abstraktní třídu TaskScheduler a přepsat následující metody.

  • QueueTask vrací void a přijímá Task objekt jako parametr a tato metoda je volána, když má být naplánován úkol
  • GetScheduledTasks vrátí seznam (přesněji IEnumerable) všech úloh, které byly naplánovány
  • TryExecuteTaskInline se používá k provádění úkolů inline, tj. V aktuálním vlákně. V tomto případě jsou úkoly provedeny bez nutnosti jejich zařazení do fronty

Následující fragment kódu ukazuje, jak můžete rozšířit třídu TaskScheduler tak, aby implementovala váš vlastní plánovač v C #.

veřejná třída CustomTaskScheduler: TaskScheduler, IDisposable

    {

    }

Jak jsme diskutovali dříve v tomto článku, budete muset přepsat metody GetScheduledTasks, QueueTask a TryExecuteTaskInline ve vlastním plánovači úloh.

veřejná zapečetěná třída CustomTaskScheduler: TaskScheduler, IDisposable

  {

chráněné přepsání IEnumerable GetScheduledTasks ()

        {

//DĚLAT

        }

chráněné přepsání void QueueTask (úkol úkolu)

        {

//DĚLAT

        }

protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)

        {

//DĚLAT

        }

public void Dispose ()

        {

//DĚLAT

        }

  }

Použijte BlockingCollection k uložení kolekce objektů úkolů v C #

Začněme nyní implementovat náš vlastní plánovač úloh. Následující fragment kódu ukazuje, jak můžete využít BlockingCollection k uložení kolekce objektů úkolů.

veřejná zapečetěná třída CustomTaskScheduler: TaskScheduler, IDisposable

 {

private BlockingCollection tasksCollection = new BlockingCollection ();

soukromé jen pro čtení Thread mainThread = null;

public CustomTaskScheduler ()

        {

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

if (! mainThread.IsAlive)

            {

mainThread.Start ();

            }

        }

private void Execute ()

        {

foreach (var task in tasksCollection.GetConsumingEnumerable ())

            {

TryExecuteTask (úkol);

            }

        } 

// Jiné metody

  }

Podívejte se na konstruktor třídy CustomTaskScheduler. Všimněte si, jak bylo vytvořeno nové vlákno a bylo spuštěno spuštění metody Execute.

Implementujte metody GetScheduledTasks, QueueTask a TryExecuteTaskInline v C #

Dále musíme implementovat tři metody, které musíme přepsat v našem vlastním plánovači úloh. Mezi tyto tři metody patří GetScheduledTasks, QueueTask a TryExecuteTaskInline.

Metoda GetScheduledTasks vrací instanci kolekce úkolů jako IEnumerable. To se používá, takže můžete výčet kolekce, jak je znázorněno v metodě Execute. Metoda QueueTask přijímá Task objekt jako parametr a ukládá jej do kolekce úkolů. Metoda TryExecuteTaskInline nemá implementaci - nechám ji na čtenáři, aby ji implementoval.

chráněné přepsání IEnumerable GetScheduledTasks ()

        {

return tasksCollection.ToArray ();

        }

chráněné přepsání void QueueTask (úkol úkolu)

        {

if (task! = null)

tasksCollection.Add (úkol);

        }

protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)

        {

návrat false;

        }

Kompletní příklad CustomTaskScheduler v C #

Následující výpis kódu ilustruje finální verzi našeho CustomTaskScheduler.

veřejná zapečetěná třída CustomTaskScheduler: TaskScheduler, IDisposable

    {

private BlockingCollection tasksCollection = new BlockingCollection ();

soukromé jen pro čtení Thread mainThread = null;

public CustomTaskScheduler ()

        {

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

if (! mainThread.IsAlive)

            {

mainThread.Start ();

            }

        }

private void Execute ()

        {

foreach (var task in tasksCollection.GetConsumingEnumerable ())

            {

TryExecuteTask (úkol);

            }

        }

chráněné přepsání IEnumerable GetScheduledTasks ()

        {

return tasksCollection.ToArray ();

        }

chráněné přepsání void QueueTask (úkol úkolu)

        {

if (task! = null)

tasksCollection.Add (úkol);

        }

protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)

        {

návrat false;

        }

private void Dispose (bool disposing)

        {

if (! disposing) return;

tasksCollection.CompleteAdding ();

tasksCollection.Dispose ();

        }

public void Dispose ()

        {

Dispose (true);

GC.SuppressFinalize (this);

        }

    }

Chcete-li použít vlastní plánovač úloh, který jsme právě implementovali, můžete použít následující fragment kódu:

CustomTaskScheduler taskScheduler = nový CustomTaskScheduler ();

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

Jak udělat více v C #:

  • Kdy použít abstraktní třídu vs. rozhraní v C #
  • Jak pracovat s AutoMapperem v C #
  • Jak používat výrazy lambda v C #
  • Jak pracovat s delegáty Action, Func a Predicate v C #
  • Jak pracovat s delegáty v C #
  • Jak implementovat jednoduchý záznamník v C #
  • Jak pracovat s atributy v C #
  • Jak pracovat s log4net v C #
  • Jak implementovat vzor návrhu úložiště v C #
  • Jak pracovat s odrazem v C #
  • Jak pracovat se souborovým systémem v C #
  • Jak provést línou inicializaci v C #
  • Jak pracovat s MSM v C #
  • Jak pracovat s metodami rozšíření v C #
  • Jak na nás lambda výrazy v C #
  • Kdy použít volatilní klíčové slovo v C #
  • Jak používat klíčové slovo výnos v C #
  • Jak implementovat polymorfismus v C #
  • Jak vytvořit svůj vlastní plánovač úloh v C #
  • Jak pracovat s RabbitM v C #
  • Jak pracovat s n-ticí v C #
  • Zkoumání virtuálních a abstraktních metod v C #
$config[zx-auto] not found$config[zx-overlay] not found