Orleans具备非常简单的异常传递机制,Grain或Placement注解逻辑抛异常,可以直接传递到客户端,测试代码如下:
首先在客户端、Silo服务程序的Main方法增加ThreadException事件处理函数,避免未处理异常导致进程闪退。
static void Main()
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
Application.ThreadException += (sender, ex) =>
{
using (var dlg = new ThreadExceptionDialog(ex.Exception))
{
dlg.ShowDialog();
}
};
ApplicationConfiguration.Initialize();
System.Windows.Forms.Application.Run(new Form1());
}
Placement逻辑抛异常代码如下,如获取id为camera3的Grain远程实例则抛异常:
public Task<SiloAddress> OnAddActivation(PlacementStrategy strategy, PlacementTarget target, IPlacementContext context)
{
var grainID = target.GrainIdentity.Key.ToString();
var silos = context.GetCompatibleSilos(target).ToArray();
SiloAddress siloAddress = silos.First();
if (grainID == "user1" || grainID == "camera1")
siloAddress = silos?.FirstOrDefault(x => x.Endpoint.Port == 11111) ?? siloAddress;
else if (grainID == "user2" || grainID == "camera2")
siloAddress = silos?.FirstOrDefault(x => x.Endpoint.Port == 11112) ?? siloAddress;
else if (grainID == "camera3")
throw new Exception("非法的graid id");
return Task.FromResult(siloAddress);
}
Grain内函数抛异常代码如下:
public async Task RunAnExceptionMethod()
{
throw new NotImplementedException("这是一个故意在服务端抛出异常的方法");
}
客户端调用后报错如下截图:
总结:Grain方法抛异常,不会影响服务端,仅在客户端执行线程异常事件处理函数(本例弹窗提示),服务端的线程异常事件处理函数没有执行(但必须有,否则服务端闪退)。