Formazione
Modulo
Creare la prima app Orleans con ASP.NET Core 8.0 - Training
Informazioni su come creare app distribuite native del cloud con Orleans.
Questo browser non è più supportato.
Esegui l'aggiornamento a Microsoft Edge per sfruttare i vantaggi di funzionalità più recenti, aggiornamenti della sicurezza e supporto tecnico.
Prima di scrivere codice per implementare una classe grain, creare un nuovo progetto libreria di classi con destinazione .NET Standard o .NET Core (preferito) o .NET Framework 4.6.1 o versione successiva (se non è possibile usare .NET Standard o .NET Core a causa delle dipendenze). Le interfacce grain e le classi grain possono essere definite nello stesso progetto libreria di classi o in due progetti diversi per una migliore separazione delle interfacce dall'implementazione. In entrambi i casi, i progetti devono fare riferimento ai pacchetti Microsoft.Orleans.Core.Abstractions e Microsoft.Orleans.CodeGenerator.MSBuild NuGet.
Per istruzioni più dettagliate, vedere la Project configurazione diTutorial One - Orleans Basics.
I grani interagiscono tra loro e vengono chiamati dall'esterno richiamando i metodi dichiarati come parte delle rispettive interfacce grain. Una classe grain implementa una o più interfacce grain dichiarate in precedenza. Tutti i metodi di un'interfaccia grain devono restituire un (per void
i metodi), un o Task<TResult>ValueTask<TResult> un (per i metodi che restituiscono valori di tipo T
).Task
Di seguito è riportato un estratto dell'esempio servizio Presence di Orleans versione 1.5:
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;
}
}
Un metodo grain che restituisce un valore di tipo T
viene definito in un'interfaccia grain come che restituisce un oggetto Task<T>
.
Per i metodi grain non contrassegnati con la async
parola chiave , quando il valore restituito è disponibile, viene in genere restituito tramite l'istruzione seguente:
public Task<SomeType> GrainMethod1()
{
return Task.FromResult(GetSomeType());
}
Un metodo grain che non restituisce alcun valore, in effetti un metodo void, viene definito in un'interfaccia grain come che restituisce un oggetto Task
. L'oggetto Task
restituito indica l'esecuzione asincrona e il completamento del metodo. Per i metodi grain non contrassegnati con la async
parola chiave , quando un metodo "void" completa l'esecuzione, deve restituire il valore speciale di Task.CompletedTask:
public Task GrainMethod2()
{
return Task.CompletedTask;
}
Un metodo grain contrassegnato come async
restituisce direttamente il valore:
public async Task<SomeType> GrainMethod3()
{
return await GetSomeTypeAsync();
}
Un void
metodo grain contrassegnato come async
che non restituisce alcun valore restituisce semplicemente alla fine dell'esecuzione:
public async Task GrainMethod4()
{
return;
}
Se un metodo grain riceve il valore restituito da un'altra chiamata di metodo asincrona a una granulosità o meno e non deve eseguire la gestione degli errori di tale chiamata, Task
può semplicemente restituire il valore ricevuto da tale chiamata asincrona:
public Task<SomeType> GrainMethod5()
{
Task<SomeType> task = CallToAnotherGrain();
return task;
}
Analogamente, un metodo grain void
può restituire un oggetto Task
restituito da un'altra chiamata anziché attenderlo.
public Task GrainMethod6()
{
Task task = CallToAsyncAPI();
return task;
}
ValueTask<T>
può essere usato al posto di Task<T>
.
Un riferimento grain è un oggetto proxy che implementa la stessa interfaccia grain della classe grain corrispondente. Incapsula l'identità logica (tipo e chiave univoca) del grano di destinazione. Un riferimento granulosità viene usato per effettuare chiamate alla granulosità di destinazione. Ogni riferimento granulosità è a una singola granulosità (una singola istanza della classe grain), ma è possibile creare più riferimenti indipendenti alla stessa granulosità.
Poiché un riferimento granulosità rappresenta l'identità logica della granulosità di destinazione, è indipendente dalla posizione fisica della granulosità e rimane valido anche dopo un riavvio completo del sistema. Gli sviluppatori possono usare riferimenti granulari come qualsiasi altro oggetto .NET. Può essere passato a un metodo, usato come valore restituito del metodo e così via, e anche salvato nell'archiviazione permanente.
È possibile ottenere IGrainFactory.GetGrain<TGrainInterface>(Type, Guid) un riferimento alla granulosità passando l'identità di una grana al metodo , T
key
dove è l'interfaccia grain e è la chiave univoca della grana all'interno del tipo.
Di seguito sono riportati esempi di come ottenere un riferimento granulare dell'interfaccia IPlayerGrain
definita in precedenza.
Dall'interno di una classe grain:
IPlayerGrain player = GrainFactory.GetGrain<IPlayerGrain>(playerId);
Dal codice client di Orleans.
IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);
Il modello di programmazione Orleans è basato sulla programmazione asincrona. Usando il riferimento alla granulosità dell'esempio precedente, ecco come eseguire una chiamata al metodo grain:
// 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);
È possibile creare un join di due Tasks
o più elementi . L'operazione di join Task
Task
crea un nuovo elemento che viene risolto al completamento di tutti i relativi componenti. Si tratta di un modello utile quando una granularità deve avviare più calcoli e attendere il completamento di tutti prima di procedere. Ad esempio, una grana front-end che genera una pagina Web fatta di molte parti potrebbe effettuare più chiamate back-end, una per ogni parte, e ricevere un Task
per ogni risultato. Il grano attende quindi il join Tasks
di tutti questi elementi. Quando il join Task
viene risolto, Task
i singoli s sono stati completati e tutti i dati necessari per formattare la pagina Web sono stati ricevuti.
Esempio:
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.
Una classe grain può facoltativamente eseguire l'override OnActivateAsyncOnDeactivateAsync dei metodi virtuali e , che vengono richiamati dal runtime di Orleans all'attivazione e alla disattivazione di ogni granulo della classe. In questo modo il codice granulare ha la possibilità di eseguire operazioni di inizializzazione e pulizia aggiuntive. Un'eccezione generata da non riesce OnActivateAsync
nel processo di attivazione.
Anche OnActivateAsync
se , se sottoposto a override, viene sempre chiamato come parte del processo di attivazione granulare, OnDeactivateAsync
non è garantito che venga chiamato in tutte le situazioni, ad esempio in caso di errore del server o di un altro evento anomalo. Di conseguenza, le applicazioni non devono basarsi su OnDeactivateAsync
per eseguire operazioni critiche, ad esempio la persistenza delle modifiche dello stato. È consigliabile usarlo solo per operazioni ottimali.
Formazione
Modulo
Creare la prima app Orleans con ASP.NET Core 8.0 - Training
Informazioni su come creare app distribuite native del cloud con Orleans.