如何获得HubProxy.Invoke调用的响应?

问题描述

所以我有一个C#client,它调用SignalR method的{​​{1}},集线器将返回一个hub

但是我现在遇到的行为是DateTime被卡在client上,最终导致记录以下内容

HubProxy.Invoke

这是Possible deadlock detected. A callback registered with "HubProxy.On" or "Connection.Received" has been executing for at least 10 seconds.代码

client

这是private async Task<long> GetCurrentServerTimeOffset() { DateTime requestDate = DateTime.Now; DateTime serverDate = await hubProxy.Invoke<DateTime>("GetCurrentServerTime"); DateTime resultDate = DateTime.Now; long offset = serverDate.Ticks - (requestDate.Ticks + resultDate.Ticks) / 2; return offset; } 代码

Hub

我已经尝试将public DateTime GetCurrentServerTime() { return DateTime.Now; } 替换为await hubProxy.Invoke<DateTime>("GetCurrentServerTime"),但其行为相同...

有人知道我在做什么错,导致记录了致命警告吗?

EDIT1 :如果我在hubProxy.Invoke<DateTime>("GetCurrentServerTime").Result的{​​{1}}中放置一个断点,则该断点将被命中,而return DateTime.Now;可以毫无问题地发送响应到hub

解决方法

这很奇怪,但是对于我来说,您的代码运行良好。客户端/服务器配置可能有问题吗?

我的简单服务器配置:

public partial class FormServer : Form
{
   private IDisposable Server { get; set; }
   private const string ServerURL = "http://localhost:8080";

   public FormServer()
   {
      InitializeComponent();
   }

   private void ButtonStart_Click(object sender,EventArgs e)
   {
      Task.Run(StartServer); 
   }

   private void StartServer()
   {
      try
      {
         Server = WebApp.Start(ServerURL);
         this.Invoke((Action)(() => buttonStart.Enabled = false)); 

         consoleTextBox.Invoke((Action)(() => consoleTextBox.AppendText($"Server successfully started on {ServerURL} {Environment.NewLine}")));
      }
      catch (TargetInvocationException ex)
      {
         consoleTextBox.Invoke((Action)(() => consoleTextBox.AppendText($"Server failed to start. Error: {ex.Message} {Environment.NewLine}")));
         return;
      }
   }
}

客户端配置:

public partial class FormClient : Form
{
   private string ServerURL = "http://localhost:8080";
   public HubConnection Connection { get; set; }
   IHubProxy HubProxy { get; set; }

   public FormClient()
   {
      InitializeComponent();
      labelAddress.Text = ServerURL;
   }

   private void Connection_StateChanged(StateChange obj)
   {
      this.Invoke((Action)(() =>
      {
         labelState.Text = Connection.State.ToString();
         if (Connection.State == ConnectionState.Disconnected) 
         {
            buttonConnect.Enabled = true;
         }
      }));
   }

   private async Task ConnectAsync()
   {
      Connection = new HubConnection(ServerURL);
      HubProxy = Connection.CreateHubProxy("MyHub"); // Hub name
      Connection.StateChanged += Connection_StateChanged;
                     
      try // try to connect to the server
      {
         await Connection.Start();
         labelState.Text = Connection.State.ToString();
      }
      catch (HttpRequestException ex) // Catch an error
      {
         this.Invoke((Action)(() =>
         {
            richTextBox.AppendText($"Error: {Environment.NewLine} {ex.Message} {Environment.NewLine}");
         }));
      }
   }

   private async void ButtonConnect_Click(object sender,EventArgs e)
   {
      await ConnectAsync();
   }

   private async void MyButton_Click(object sender,EventArgs e)
   {
      long result = await GetCurrentServerTimeOffset();
      MessageBox.Show(result.ToString());
   }

   private async Task<long> GetCurrentServerTimeOffset()
   {
      DateTime requestDate = DateTime.Now;
      DateTime serverDate = await HubProxy.Invoke<DateTime>("GetCurrentServerTime");
      DateTime resultDate = DateTime.Now;

      long offset = serverDate.Ticks - (requestDate.Ticks + resultDate.Ticks) / 2;

      return offset;
   }
}

SignalR集线器:

public class MyHub : Hub
{
   public DateTime GetCurrentServerTime() => DateTime.Now;
}
,

能够通过不等待它自己修复它:

_radioHubProxy.Invoke<DateTime>("GetCurrentServerTime").ContinueWith(response =>
{
    DateTime serverDate = response.Result;
    DateTime resultDate = DateTime.UtcNow;
    long offset = serverDate.Ticks - (requestDate.Ticks + resultDate.Ticks) / 2;
    _mobi.SetServerTimeOffset(offset);
});