Omówienie planowania
Istnieją dwie formy planowania, w Orleans których są istotne dla ziarna:
- Planowanie żądań, planowanie przychodzących wywołań ziarna do wykonania zgodnie z regułami planowania omówionymi w temacie Planowanie żądań.
- Planowanie zadań, planowanie synchronicznych bloków kodu do wykonania w sposób jednowątkowy
Cały kod ziarna jest wykonywany w harmonogramie zadań ziarna, co oznacza, że żądania są również wykonywane w harmonogramie zadań ziarna. Nawet jeśli reguły planowania żądań zezwalają na współbieżne wykonywanie wielu żądań, nie będą one wykonywane równolegle, ponieważ harmonogram zadań ziarna zawsze wykonuje zadania jeden po jednym i dlatego nigdy nie wykonuje wielu zadań równolegle.
Planowanie zadań
Aby lepiej zrozumieć planowanie, rozważ następujące ziarno, MyGrain
które ma metodę o nazwie DelayExecution()
, która rejestruje komunikat, czeka trochę czasu, a następnie rejestruje kolejny komunikat przed zwróceniem.
public interface IMyGrain : IGrain
{
Task DelayExecution();
}
public class MyGrain : Grain, IMyGrain
{
private readonly ILogger<MyGrain> _logger;
public MyGrain(ILogger<MyGrain> logger) => _logger = logger;
public async Task DelayExecution()
{
_logger.LogInformation("Executing first task");
await Task.Delay(1_000);
_logger.LogInformation("Executing second task");
}
}
Po wykonaniu tej metody treść metody zostanie wykonana w dwóch częściach:
- Pierwsze
_logger.LogInformation(...)
wywołanie i wywołanie metody .Task.Delay(1_000)
- Drugie
_logger.LogInformation(...)
wywołanie.
Drugie zadanie nie zostanie zaplanowane zgodnie z harmonogramem zadań ziarna, dopóki Task.Delay(1_000)
wywołanie nie zostanie zakończone, w którym momencie zaplanuje kontynuację metody ziarna.
Oto graficzna reprezentacja sposobu planowania i wykonywania żądania jako dwóch zadań:
Powyższy opis nie jest specyficzny dla Orleans funkcji planowania zadań na platformie .NET: metody asynchroniczne w języku C# są konwertowane na maszynę stanu asynchronicznego przez kompilator i wykonywanie postępuje przez maszynę stanu asynchronicznego w dyskretnych krokach. Każdy krok jest zaplanowany dla bieżącego TaskScheduler (dostępnego za pośrednictwem TaskScheduler.Current, domyślnie na TaskScheduler.Default) lub bieżącego SynchronizationContext. TaskScheduler
Jeśli element jest używany, każdy krok w metodzie jest reprezentowany przez Task
wystąpienie, które jest przekazywane do tego TaskScheduler
elementu . W związku z tym element na Task
platformie .NET może reprezentować dwie koncepcje:
- Operacja asynchroniczna, którą można zaczekać. Wykonanie powyższej
DelayExecution()
metody jest reprezentowane przezTask
element, którego można oczekiwać. - W synchronicznym bloku pracy każdy etap w
DelayExecution()
powyższej metodzie jest reprezentowany przezTask
element .
Gdy TaskScheduler.Default
jest w użyciu, kontynuacje są zaplanowane bezpośrednio na platformie .NET ThreadPool i nie są opakowane w Task
obiekt. Zawijanie kontynuacji w Task
wystąpieniach odbywa się w sposób niewidoczny i dlatego deweloperzy rzadko muszą być świadomi tych szczegółów implementacji.
Planowanie zadań w programie Orleans
Każda aktywacja ziarna ma własne TaskScheduler
wystąpienie, które jest odpowiedzialne za wymuszanie modelu wykonywania jednowątkowego ziarna. Wewnętrznie jest to TaskScheduler
implementowane za pośrednictwem metod ActivationTaskScheduler
i WorkItemGroup
. WorkItemGroup
program przechowuje zadania w kolejce w miejscu Queue<T> , gdzie T
jest Task
wewnętrznie i implementuje IThreadPoolWorkItem. Aby wykonać każdą aktualnie w kolejce Task
, WorkItemGroup
harmonogramy są wykonywane na platformie .NET ThreadPool
. Gdy platforma .NET ThreadPool
wywołuje WorkItemGroup
metodę "s IThreadPoolWorkItem.Execute()
", WorkItemGroup
funkcja wykonuje w kolejce Task
wystąpienia jeden po jednym.
Każde ziarno ma harmonogram, który jest wykonywany przez zaplanowanie się na platformie .NET ThreadPool
:
Każdy harmonogram zawiera kolejkę zadań:
Platforma .NET ThreadPool
wykonuje każdy element roboczy w kolejce. Obejmuje to harmonogramy ziarna, a także inne elementy robocze, takie jak elementy robocze zaplanowane za pomocą polecenia Task.Run(...)
:
Uwaga
Harmonogram ziarna może być wykonywany tylko w jednym wątku jednocześnie, ale nie zawsze jest wykonywany w tym samym wątku. Platforma .NET ThreadPool
może używać innego wątku za każdym razem, gdy harmonogram ziarna jest wykonywany. Harmonogram ziarna jest odpowiedzialny za upewnienie się, że wykonuje tylko jeden wątek w danym momencie i tak jest implementowany model wykonywania pojedynczego wątku ziarna.