Sdílet prostřednictvím


Vývoj zrnitosti

před psaním kódu pro implementaci třídy zrnitosti vytvořte nový projekt knihovny tříd cílící na .NET Standard nebo .Net Core (upřednostňovaný) nebo .NET Framework 4.6.1 nebo vyšší (pokud nemůžete použít .NET Standard nebo .net Core z důvodu závislostí). Rozhraní zrnitosti a třídy zrnitosti lze definovat ve stejném projektu knihovny tříd nebo ve dvou různých projektech pro lepší oddělení rozhraní od implementace. v obou případech musí projekty odkazovat na microsoft. Orleans. Core. abstractions a microsoft. Orleans. CodeGenerator. MSBuild NuGet balíčky.

podrobnější pokyny najdete v části věnované nastavení Projectkurzu One – Orleans základy.

Rozhraní a třídy zrnitosti

Zrna vzájemně komunikují a volají se z vnějšku vyvoláním metod deklarovaných jako součást příslušných rozhraní zrnitosti. Třída zrnitosti implementuje jedno nebo více dříve deklarovaných rozhraní zrn. Všechny metody rozhraní zrnitosti musí vracet Task (pro void metody), a ValueTask<TResult>Task<TResult> (pro metody, které vracejí hodnoty typu T ).

V následujícím příkladu je ukázka služby Orleans verze 1,5 pro službu stavu:

public interface IPlayerGrain : IGrainWithGuidKey
{
    Task<IGameGrain> GetCurrentGame();
    Task JoinGame(IGameGrain game);
    Task LeaveGame(IGameGrain game);
}

public class PlayerGrain : Grain, IPlayerGrain
{
    private IGameGrain _currentGame;

    // Game the player is currently in. May be null.
    public Task<IGameGrain> GetCurrentGame()
    {
       return Task.FromResult(_currentGame);
    }

    // Game grain calls this method to notify that the player has joined the game.
    public Task JoinGame(IGameGrain game)
    {
       _currentGame = game;

       Console.WriteLine(
           $"Player {GetPrimaryKey()} joined game {game.GetPrimaryKey()}");

       return Task.CompletedTask;
    }

   // Game grain calls this method to notify that the player has left the game.
   public Task LeaveGame(IGameGrain game)
   {
       _currentGame = null;

       Console.WriteLine(
           $"Player {GetPrimaryKey()} left game {game.GetPrimaryKey()}");

       return Task.CompletedTask;
   }
}

Návratové hodnoty z metod zrnitosti

Metoda zrnitosti, která vrací hodnotu typu T , je definována v rozhraní zrn jako vrácení Task<T> . Pro metody zrnitosti, které nejsou označeny async klíčovým slovem, je při dostupnosti návratové hodnoty obvykle vráceno pomocí následujícího příkazu:

public Task<SomeType> GrainMethod1()
{
    return Task.FromResult(GetSomeType());
}

Metoda zrnitosti, která nevrací žádnou hodnotu, je efektivní metodou void, je definována v rozhraní zrn jako vrácení Task . Vrácený Task indikuje asynchronní spuštění a dokončení metody. Pro metody zrnitosti, které nejsou označeny async klíčovým slovem, když metoda void dokončí své spuštění, musí vrátit zvláštní hodnotu Task.CompletedTask :

public Task GrainMethod2()
{
    return Task.CompletedTask;
}

Metoda zrnitosti označená jako async vrátí hodnotu přímo:

public async Task<SomeType> GrainMethod3()
{
    return await GetSomeTypeAsync();
}

voidMetoda zrnitosti označená jako async , která nevrací žádnou hodnotu, jednoduše vrátí na konci jejího spuštění:

public async Task GrainMethod4()
{
    return;
}

Pokud metoda zrnitosti obdrží vrácenou hodnotu z jiného volání asynchronní metody, do zrnitosti nebo ne, a není nutné provádět zpracování chyb tohoto volání, může jednoduše vrátit Task z tohoto asynchronního volání:

public Task<SomeType> GrainMethod5()
{
    Task<SomeType> task = CallToAnotherGrain();

    return task;
}

voidPodobně metoda zrnitosti může vrátit Task zpět pomocí jiného volání namísto čekání.

public Task GrainMethod6()
{
    Task task = CallToAsyncAPI();
    return task;
}

ValueTask<T> lze použít místo Task<T> .

Odkaz na zrno

Odkaz na zrno je objekt proxy, který implementuje stejné rozhraní zrnitosti jako odpovídající třída zrnitosti. Zapouzdřuje logickou identitu (typ a jedinečný klíč) cílové zrnitosti. Odkaz na zrno se používá pro volání do cílové zrnitosti. Každý odkaz na zrno je jedním z zrn (jedna instance třídy zrnitého), ale jedna může vytvořit více nezávislých odkazů na stejnou část.

Vzhledem k tomu, že odkaz na zrno představuje logickou identitu cílové zrnitosti, je nezávislý na fyzickém umístění zrn a zůstává platný i po úplném restartování systému. Vývojáři mohou používat odkazy na zrno jako jakýkoli jiný objekt .NET. Dá se předat metodě, která se používá jako návratová hodnota metody atd., a dokonce i Uložit do trvalého úložiště.

Odkaz na zrno lze získat předáním identity zrnitosti do IGrainFactory.GetGrain<TGrainInterface>(Type, Guid) metody, kde T je rozhraní zrnitého a key je jedinečným klíčem zrn v rámci typu.

Níže jsou uvedeny příklady, jak získat odkaz IPlayerGrain na zrno rozhraní definované výše.

Z uvnitř třídy zrnitosti:

IPlayerGrain player = GrainFactory.GetGrain<IPlayerGrain>(playerId);

Z klientského kódu Orleans.

IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);

Vyvolání metody zrnitosti

Programovací model Orleans je založen na asynchronním programování. Pomocí odkazu na zrno z předchozího příkladu můžete provést vyvolání metody zrnitosti:

// Invoking a grain method asynchronously
Task joinGameTask = player.JoinGame(this);

// The await keyword effectively makes the remainder of the
// method execute asynchronously at a later point
// (upon completion of the Task being awaited) without blocking the thread.
await joinGameTask;

// The next line will execute later, after joinGameTask has completed.
players.Add(playerId);

Je možné spojit dva nebo více Tasks . operace join vytvoří nový Task , který se vyřeší po dokončení všech jeho prvků Task . Tento model je užitečný, pokud je potřeba, aby zrna spouštěla více výpočetních prostředků a před pokračováním čekala na dokončení všech. Například přední konec zrnitosti, který generuje webovou stránku tvořenou mnoha částmi, může vytvořit několik back-endové volání, jednu pro každou část a získat Task pro každý výsledek. Zrnitost by pak čekala na spojení všech těchto Tasks . když se spojení Task vyřeší, jednotlivec Task s byl dokončen a všechna data potřebná k formátování webové stránky byly přijaty.

Příklad:

List<Task> tasks = new List<Task>();
Message notification = CreateNewMessage(text);

foreach (ISubscriber subscriber in subscribers)
{
    tasks.Add(subscriber.Notify(notification));
}

// WhenAll joins a collection of tasks, and returns a joined
// Task that will be resolved when all of the individual notification Tasks are resolved.
Task joinedTask = Task.WhenAll(tasks);

await joinedTask;

// Execution of the rest of the method will continue
// asynchronously after joinedTask is resolve.

Virtuální metody

Třída zrnitosti může volitelně přepsat OnActivateAsync a OnDeactivateAsync virtuální metody, které jsou vyvolány modulem runtime Orleans po aktivaci a deaktivaci každé zrnitosti třídy. Díky tomu může kód zrnitosti provést další operace inicializace a vyčištění. Výjimka vyvolaná OnActivateAsync v procesu aktivace se nezdařila. OnActivateAsyncV případě, že je přepsána, je vždy volána jako součást procesu aktivace zrnitosti, OnDeactivateAsync není zaručeno volání ve všech situacích, například v případě selhání serveru nebo jiné neobvyklé události. Z toho důvodu by aplikace neměly spoléhat na OnDeactivateAsync provádění kritických operací, jako je například trvalá změna stavu. Měly by se používat jenom pro nejvyšší úsilí.