在编写代码以实现Grain
类之前,在Visual Studio中创建一个新的针对.NET 4.6.1或更高版本的类库项目,并为其添加NuGet包。Microsoft.
Orleans
.Orleans
CodeGenerator.Build
PM> Install-Package Microsoft.Orleans.OrleansCodeGenerator.Build
通过调用声明为相应Grain
接口的一部分的方法,谷物相互交互并从外部调用。一个Grain
类实现了一个或多个先前声明的Grain
接口。Grain
接口的所有方法必须返回一个Task
(对于void
方法)或一个Task
(对于返回类型值的方法T
)。
以下是Presence服务示例的摘录:
//an example of a Grain Interface
public interface IPlayerGrain : IGrainWithGuidKey
{
Task GetCurrentGame() ;
Task JoinGame(IGameGrain game);
Task LeaveGame(IGameGrain game);
}
//an example of a Grain class implementing a Grain Interface
public class PlayerGrain : Grain, IPlayerGrain
{
private IGameGrain currentGame;
// Game the player is currently in. May be null.
public Task 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 {0} joined game {1}",
this.GetPrimaryKey(),
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 {0} left game {1}",
this.GetPrimaryKey(),
game.GetPrimaryKey());
return Task.CompletedTask;
}
}
甲Grain
返回类型的值的方法T
是在限定的Grain
界面为返回一个Task
。对于Grain
未用async
关键字标记的方法,当返回值可用时,通常通过以下语句返回:
public Task GrainMethod1()
{
...
return Task.FromResult();
}
甲Grain
不返回值,有效的空隙的方法的方法,在一个被定义Grain
的接口为返回Task
。返回Task
值表示异步执行和方法的完成。对于Grain
未用async
关键字标记的方法,当“void”方法完成其执行时,它需要返回特殊值Task.CompletedTask
:
public Task GrainMethod2()
{
...
return Task.CompletedTask;
}
Grain
标记为的方法async
直接返回值:
public async Task GrainMethod3()
{
...
return ;
}
一个Grain
标记为“void”的方法async
在执行结束时不会返回任何值。
public async Task GrainMethod4()
{
...
return;
}
如果一个Grain
方法接收到来自另一个异步方法调用的返回值Grain
,并且不需要执行该调用的错误处理,则它可以简单地将Task
它从该异步调用接收到的返回值作为其返回值:
public Task GrainMethod5()
{
...
Task task = CallToAnotherGrain();
return task;
}
同样,“void” Grain
方法可以Task
通过另一个调用返回给它,而不是等待它。
public Task GrainMethod6()
{
...
Task task = CallToAsyncAPI();
return task;
}
Grain
参考是实现相同的代理对象Grain
接口作为相应Grain
类。它封装了目标的逻辑标识(类型和唯一键)Grain
。一个Grain
基准就是用于制作到目标调用Grain
。每个Grain
引用都是针对单个Grain
(类的单个实例Grain
),但可以为同一个引用创建多个独立引用Grain
。
由于Grain
引用表示目标的逻辑身份Grain
,因此它独立于该目标的物理位置Grain
,并且即使在系统完全重新启动后仍保持有效。开发人员可以Grain
像使用其他.NET对象一样使用引用。它可以传递给一个方法,用作方法的返回值等等,甚至保存到持久存储中。
甲Grain
参考可以通过传递的身份来获得Grain
对GrainFactory.GetGrain
方法,其中T
是Grain
接口和key
是的唯一密钥Grain
的类型内。
以下是如何获取上面定义Grain
的IPlayerGrain
接口的引用的示例。
从Grain
课堂内部:
//construct the grain reference of a specific player
IPlayerGrain player = GrainFactory.GetGrain(playerId);
从Orleans
客户端代码。
在1.5.0之前:
IPlayerGrain player = GrainClient.GrainFactory.GetGrain(playerId);
由于1.5.0:
IPlayerGrain player = client.GetGrain(playerId);
该Orleans
编程模型是基于异步编程与异步和等待。
使用Grain
前面示例中的参考,以下是执行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 is completed.
players.Add(playerId);
有可能加入两个或更多Tasks
; 连接操作会创建一个新的Task
,当其所有组成Task
部分完成时都会解析。当Grain
需要启动多个计算并在继续之前等待所有计算完成时,这是一个有用的模式。例如,Grain
生成由多个部分组成的网页的前端可能会进行多个后端调用,每个部分一个,并Task
为每个结果接收一个。在Grain
随后将等待加入所有这些的Tasks
; 当连接Task
被解决时,个人Task
已经完成,并且已经接收到格式化网页所需的所有数据。
例:
List tasks = new List();
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.
一个Grain
类可以可选地覆盖OnActivateAsync
和OnDeactivateAsync
虚拟方法,这些方法Orleans
在每个Grain
类的激活和去激活时由运行时调用。这使Grain
代码有机会执行额外的初始化和清理操作。由OnActivateAsync
激活过程失败引发的异常。虽然OnActivateAsync
如果被覆盖,总是作为Grain
激活过程的一部分被调用,但OnDeactivateAsync
不能保证在所有情况下被调用,例如,在服务器故障或其他异常事件的情况下。因此,应用程序不应该依赖OnDeactivateAsync来执行关键操作,例如状态更改的持久性,只能将其用于尽力而为的操作。
开发一个客户