Översikt över schemaläggning
Det finns två typer av schemaläggning Orleans som är relevanta för korn:
- Schemaläggning av begäranden, schemaläggning av inkommande korn kräver körning enligt schemaläggningsregler som beskrivs i Schemaläggning av begäranden.
- Uppgiftsschemaläggning, schemaläggning av synkrona kodblock som ska köras på ett enkelt trådat sätt
All kornkod körs på kornets schemaläggare, vilket innebär att begäranden också körs på kornets schemaläggare. Även om reglerna för schemaläggning av begäranden tillåter att flera begäranden körs samtidigt, körs de inte parallellt eftersom kornets schemaläggare alltid kör uppgifter en i taget och därför aldrig kör flera uppgifter parallellt.
Schemalägga aktivitet
För att bättre förstå schemaläggningen bör du överväga följande korn, MyGrain
, som har en metod som heter DelayExecution()
som loggar ett meddelande, väntar en stund och loggar sedan ett annat meddelande innan det returneras.
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");
}
}
När den här metoden körs körs metodtexten i två delar:
- Det första
_logger.LogInformation(...)
anropet och anropet tillTask.Delay(1_000)
. - Det andra
_logger.LogInformation(...)
samtalet.
Den andra aktiviteten schemaläggs inte i kornets schemaläggare förrän anropet Task.Delay(1_000)
har slutförts. Då schemaläggs fortsättningen av kornmetoden.
Här är en grafisk representation av hur en begäran schemaläggs och körs som två uppgifter:
Beskrivningen ovan är inte specifik för Orleans och är hur aktivitetsschemaläggning i .NET fungerar: asynkrona metoder i C# konverteras till en asynkron tillståndsdator av kompilatorn och körningen förlopp via den asynkrona tillståndsdatorn i diskreta steg. Varje steg schemaläggs på den aktuella TaskScheduler (nås via TaskScheduler.Current, som standard till TaskScheduler.Default) eller den aktuella SynchronizationContext. Om en TaskScheduler
används representeras varje steg i metoden av en Task
instans som skickas till den TaskScheduler
. Därför kan en Task
i .NET representera två konceptuella saker:
- En asynkron åtgärd som kan väntas på. Körningen
DelayExecution()
av metoden ovan representeras av enTask
som kan inväntas. - I ett synkront arbetsblock representeras varje steg i
DelayExecution()
metoden ovan av enTask
.
När TaskScheduler.Default
används schemaläggs fortsättningar direkt till .NET ThreadPool och omsluts inte i ett Task
objekt. Omslutningen av fortsättningar i Task
instanser sker transparent och därför behöver utvecklare sällan vara medvetna om dessa implementeringsuppgifter.
Schemaläggning av aktiviteter i Orleans
Varje kornaktivering har en egen TaskScheduler
instans som ansvarar för att framtvinga entrådad körningsmodell med korn. Internt implementeras detta TaskScheduler
via ActivationTaskScheduler
och WorkItemGroup
. WorkItemGroup
håller enqueued uppgifter i en Queue<T> där T
är en Task
internt och implementerar IThreadPoolWorkItem. Om du vill köra var och en som för närvarande är enqueued Task
WorkItemGroup
schemalägger sig på .NET ThreadPool
. När .NET ThreadPool
anropar WorkItemGroup
metoden WorkItemGroup
's IThreadPoolWorkItem.Execute()
kör den enqueued-instanserna Task
en i taget.
Varje korn har en schemaläggare som körs genom att schemalägga sig själv på .NET ThreadPool
:
Varje schemaläggare innehåller en kö med uppgifter:
.NET ThreadPool
kör varje arbetsobjekt som anges i den. Detta inkluderar kornschemaläggare och andra arbetsobjekt, till exempel arbetsobjekt som schemalagts via Task.Run(...)
:
Kommentar
Ett korns schemaläggare kan bara köras på en tråd i taget, men den körs inte alltid på samma tråd. .NET ThreadPool
kan använda en annan tråd varje gång kornets schemaläggare körs. Kornets schemaläggare ansvarar för att se till att den bara körs på en tråd i taget och det är så den enkla trådade körningsmodellen för korn implementeras.