设置

在编写实现grain类的代码之前,请新建一个面向.NET Standard(首选)、或.NET Framework 4.6.1或更高版本的类库项目(如果由于依赖性而无法使用.NET Standard)。grain接口和grain类可以在同一个类库项目中定义,也可以在两个不同的项目中定义,以便更好地分离接口和实现。无论哪种情况,项目都需要引用Microsoft.Orleans.Core.Abstractions和Microsoft.Orleans.CodeGenerator.MSBuildNuGet包。

有关更详细的说明,请参阅Tutorial One - Orleans Basics的Project Setup部分。

grain接口和类

grain之间能彼此交互,它能被外部调用其方法,这些方法是grain接口声明中的一部分。grain类实现一个或多个先前声明的grain接口。grain接口的所有方法都必须返回一个 Task(对于void方法)、一个 Task或一个 ValueTask(对于返回类型值的类型为T的方法)。

以下是Orleans 1.5版的Presence Service示例的摘录:

//an example of a Grain Interface
public interface IPlayerGrain : IGrainWithGuidKey
{Task<IGameGrain> 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<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 {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方法,在grain接口中定义为返回一个 Task。对于未标记async关键字的grain的方法,当返回值可用时,通常通过以下语句返回:

public Task<SomeType> GrainMethod1()
{...return Task.FromResult(<variable or constant with result>);
}

一个不返回值的grain方法,实际上是一个void方法,在grain接口中定义为返回一个Task。返回Task表示异步执行和方法的完成。对于未标记async关键字的grain方法,当“void”方法完成其执行时,需要返回以下特殊值Task.CompletedTask:

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

标记为async的grain的方法,直接返回值:

public async Task<SomeType> GrainMethod3()
{...return <variable or constant with result>;
}

一个“void”的grain的方法,若被标记为async,则不返回任何值,只是在执行结束时返回:

public async Task GrainMethod4()
{...return;
}

如果一个grain方法,接收从另一个异步方法调用的返回值,无论此异步调用是不是grain的方法,都不需要对该调用执行错误处理,它只需简单地将从该异步调用接收的Task,作为其返回值:

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

类似地,一个“void”的grain的方法,可以返回另一个调用返回给它的Task,而不是await它。

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

ValueTask 可以用来代替 Task。

grain引用

一个grain引用是一个代理对象,它实现了与对应的grain类相同的grain接口。它封装了目标grain的逻辑标识(类型和唯一键)。使用grain引用,来调用目标grain。每个grain引用只能用于单个grain(grain类的单个实例),但是可以为同一grain创建多个独立的引用。

由于grain引用表示目标grain的逻辑标识,因此它与grain的物理位置无关,即使在系统彻底重新启动后,也保持有效。开发人员可以像任何其他.NET对象一样使用grain引用。它可以传递给一个方法,用作方法的返回值等,甚至可以保存到持久存储中。

可以通过将grain的标识,传递给GrainFactory.GetGrain(key)方法,来获得grain引用,其中,T是grain的接口,而key是该类型中grain的唯一键。

以下演示了如何获得上文中定义的IPlayerGrain接口的grain引用。

从grain类的内部:

    //construct the grain reference of a specific playerIPlayerGrain player = GrainFactory.GetGrain<IPlayerGrain>(playerId);

从Orleans的client:

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

grain的方法调用

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);

可以join两个或更多个Tasks;join操作创建一个Task,在其所有组成任务都完成之后,该Task完成。当一个grain需要启动多个计算,并等待这些计算完成才能继续时,这种模式很有用。例如,生成网页(由多个部分组成)的前端grain,可能会产生多个后端调用,一个部分一个调用,并为每个结果接收一个Task。然后,grain将await这些Tasks的join; 当join的Task完成,则各个Task已经完成,且已经收到格式化网页所需的所有数据。

例:

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.

虚方法
grain类可以选择性地重写OnActivateAsync和OnDeactivateAsync虚方法,这些方法在类的每个grain激活和停用时,由Orleans运行时调用。这使grain代码有机会执行额外的初始化和清理操作。若OnActivateAsync抛出异常,则激活失败。虽然OnActivateAsync(如果被重写)总是作为grain激活过程的一部分被调用,但OnDeactivateAsync不保证在所有情况下都被调用,例如,在服务器故障或其他异常事件的情况下。因此,应用程序不应依赖OnDeactivateAsync来执行关键操作,例如状态更改的持久化。应用程序应只用它于力所能及的操作。

转载:https://blog.csdn.net/uddiqpl/article/details/86162692

Orleans 2.0 官方文档 —— 开发一个Grain相关推荐

  1. Orleans 2.0 官方文档中文版 (闫辉)

    目录 第一章 概览 1.1 概览 -> 介绍 1.2 概览 -> 优点 1.3 概览 -> 常见问题 1.4 概览 -> Orleans 2.0 1.5 概览 -> Or ...

  2. Orleans 2.0 官方文档 —— 4.1 Grains - 开发一个Grain

    设置 在编写实现grain类的代码之前,请新建一个面向.NET Standard(首选).或.NET Framework 4.6.1或更高版本的类库项目(如果由于依赖性而无法使用.NET Standa ...

  3. Orleans 2.0 官方文档 —— 4.5 Grains - 观察者

    观察者 在某些情况下,简单的消息/响应模式是不够的,客户端需要接收异步通知.例如,用户可能希望在朋友发布新的即时消息时得到通知. 客户端的观察者是一种允许异步通知客户端的机制.观察者是从IGranob ...

  4. Orleans 2.0 官方文档 —— 3.1 核心概念 - 什么是grain

    什么是grain? grain是Orleans编程模型的关键原语.grain是Orleans应用程序的构建块,它们是隔离的.分布式的.持久性的原子单元.grain是表示应用程序实体的对象.就像在经典的 ...

  5. Orleans 2.0 官方文档 —— 4.4 Grains - 定时器和提醒器(Reminder)

    定时器和提醒器(Reminder) Orleans运行时提供了两种机制,称为定时器和提醒器,使开发人员能够指定grain的周期性行为. 计时器 定时器说明 定时器用于创建不需要跨越多个激活(grain ...

  6. Orleans 2.0 官方文档 —— 8.5 实现细节 - 集群管理

    Orleans的集群管理 Orleans通过内置的成员资格协议,提供了集群管理,我们有时将其称为Silo 成员资格 (Silo Membership).该协议的目标是让所有silo(Orleans服务 ...

  7. Orleans 2.0 官方文档 ——Grains定时器和提醒器(Reminder)

    定时器和提醒器(Reminder) Orleans运行时提供了两种机制,称为定时器和提醒器,使开发人员能够指定grain的周期性行为. 定时器说明 定时器用于创建不需要跨越多个激活(grain的实例化 ...

  8. Orleans 2.0 官方文档 —— 4.8.1 Grains - Grain持久化 - grain持久化的目标

    grain持久化的目标 允许不同的grain类型,使用不同类型的存储提供程序(例如,一个使用Azure表,一个使用ADO.NET),或相同类型的存储提供程序但具有不同的配置(例如,两者都使用Azure ...

  9. Orleans 2.0 官方文档 —— 5.2 集群和客户端 - silo的生命周期

    silo的生命周期 概述 Orleans silo使用可观察的生命周期(参见Orleans Lifecycle),来有序地启动和关闭Orleans系统以及应用程序层组件. 阶段 Orleans Sil ...

最新文章

  1. 改改 Python 代码,运行速度还能提升 6 万倍,Science:先别想摩尔定律了
  2. 一个爬虫的故事:爬虫兄弟要活不下去了!!!
  3. bash 判断 os 版本_专家:鸿蒙OS初登手机令人惊艳,但全面商用至少还要2年
  4. 前台后台进程转换问题
  5. Linux centos6.7 关闭防火墙
  6. RESTful 架构风格概述
  7. CRM BSP里控制左右对应对齐的属性align
  8. 一个娃娃竟然拍出50万......
  9. python读取超大文件-强悍的Python读取大文件的解决方案
  10. 分解模式 - 按业务领域分解模式划分微服务
  11. 精益思想如何加速企业的全局价值流动?
  12. win7+linux双系统安装
  13. Elasticsearch搜索引擎一些参数含义和用法
  14. python无法打开文件filenotfounderror_解决Python在导入文件时的FileNotFoundError问题
  15. Ubuntu 16.04 安装Tensorflow Object Detection API (一)
  16. Tkinter:文本框Entry
  17. canvas制作简单钟表
  18. 编译安卓系统源码jack-server问题入坑,全网最全解决方法
  19. 简单有力的一招教你摆脱拖延症
  20. Scrum: 在软件开发中应用80:20规则

热门文章

  1. 科技的成就(四十五)
  2. 频繁开关油烟净化器能节电?是真的吗?
  3. python安装lxml_python 安装lxml
  4. 开课吧T31项目第10天
  5. Vue 实现导航栏滑到顶部固定,滑动到相应位置导航栏有相应选中效果,点击导航跳转到对应位置
  6. 650个常用网页图标PSD素材
  7. .NET 实现RSA加密解密 C#
  8. mysql delimiter 异常_MySql中的DELIMITER错误
  9. kingroot权限管理_KingRoot(授权管理)
  10. NLP的游戏规则从此改写?从word2vec, ELMo到BERT