简体   繁体   English

使用 gRPC 的观察者模式 - C#

[英]Observer pattern using gRPC - C#

Sorry, if this is a stupid question but I don't find any useful information in the internet.抱歉,如果这是一个愚蠢的问题,但我在互联网上找不到任何有用的信息。

Has anyone ever tried to implement the observer pattern in C# using gRPC as communication?有没有人尝试过使用 gRPC 作为通信在 C# 中实现观察者模式? If yes, please show me the link.如果是,请告诉我链接。

Many thanks in advance and best regards.非常感谢提前和最好的问候。

I have implemented a client convenience class wrapper to turn server streaming calls into regular events for a project I am working.我已经实现了客户端便利 class 包装器,以将服务器流式调用转换为我正在工作的项目的常规事件。 Not sure if this is what you are after.不确定这是否是您所追求的。 Here is a simple gRPC server that just publishes the time as a string once every second.这是一个简单的 gRPC 服务器,它每秒将时间作为字符串发布一次。

syntax = "proto3";
package SimpleTime;

service SimpleTimeService
{
   rpc MonitorTime(EmptyRequest) returns (stream TimeResponse);
}

message EmptyRequest{}

message TimeResponse
{
   string time = 1;
}

The server implementation, which just loops once a second returning the string representation of the current time until canceled, is as follows服务器实现,它每秒只循环一次,返回当前时间的字符串表示,直到取消,如下所示

public override async Task MonitorTime(EmptyRequest request, IServerStreamWriter<TimeResponse> responseStream, ServerCallContext context)
{
   try
   {
      while (!context.CancellationToken.IsCancellationRequested)
      {
         var response = new TimeResponse
         {
            Time = DateTime.Now.ToString()
         };
         await responseStream.WriteAsync(response);
         await Task.Delay(1000);
      }
   }
   catch (Exception)
   { 
      Console.WriteLine("Exception on Server");
   }
}

For the client, I created a class that contains the gRPC client and exposes the results of the server streaming MonitorTime call as a plain ole .net event.对于客户端,我创建了一个包含 gRPC 客户端的 class 并将服务器流式 MonitorTime 调用的结果公开为普通的 ole .net 事件。

   public class SimpleTimeEventClient
   {
      private SimpleTime.SimpleTimeService.SimpleTimeServiceClient mClient = null;
      private CancellationTokenSource mCancellationTokenSource = null;
      private Task mMonitorTask = null;
      public event EventHandler<string> OnTimeReceived;

      public SimpleTimeEventClient()
      {
         Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure);
         mClient = new SimpleTime.SimpleTimeService.SimpleTimeServiceClient(channel);
      }

      public void Startup()
      {
         mCancellationTokenSource = new CancellationTokenSource();
         mMonitorTask = Task.Run(() => MonitorTimeServer(mCancellationTokenSource.Token));
      }

      public void Shutdown()
      {
         mCancellationTokenSource.Cancel();
         mMonitorTask.Wait(10000);
      }

      private async Task MonitorTimeServer(CancellationToken token)
      {
         try
         {
            using (var call = mClient.MonitorTime(new SimpleTime.EmptyRequest()))
            {
               while(await call.ResponseStream.MoveNext(token))
               {
                  var timeResult = call.ResponseStream.Current;
                  OnTimeReceived?.Invoke(this, timeResult.Time);
               }
            }
         }
         catch(Exception e)
         {
            Console.WriteLine($"Exception encountered in MonitorTimeServer:{e.Message}");
         }
      }
   }

Now create the client and subscribe to the event.现在创建客户端并订阅事件。

  static void Main(string[] args)
  {
     SimpleTimeEventClient client = new SimpleTimeEventClient();
     client.OnTimeReceived += OnTimeReceivedEventHandler;
     client.Startup();
     Console.WriteLine("Press any key to exit");
     Console.ReadKey();
     client.Shutdown();

  }

  private static void OnTimeReceivedEventHandler(object sender, string e)
  {
     Console.WriteLine($"Time: {e}");
  }

Which when run produces运行时会产生哪个

在此处输入图像描述

I have left out a lot of error checking and such to make the example smaller.我省略了很多错误检查,以使示例更小。 One thing I have done is for gRPC interfaces with many server streaming calls that may or may not be of interest to call clients, is to implement the event accessor (add,remove) to only call the server side streaming method if there is a client that has subscribed to the wrapped event.我所做的一件事是为 gRPC 接口与许多服务器流式调用可能会或可能不会调用客户端感兴趣,是实现事件访问器(添加,删除)仅在有客户端时调用服务器端流式传输方法订阅了包装的事件。 Hope this is helpful希望这有帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM