Как получить ответ на вызов HubProxy.Invoke?

Итак, у меня есть C# client который вызывает method SignalR 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") с участием hubProxy.Invoke<DateTime>("GetCurrentServerTime").Result но ведет себя так же...

Кто-нибудь знает, что я делаю не так, из-за чего предупреждение о дедлайне регистрируется?

EDIT1: если я поставлю точку останова вreturn DateTime.Now; из hub, точка останова достигнута, а hub не имеет проблем с отправкой своего ответа на client.

2 ответа

Я смог исправить это сам, заставив его не ждать:

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

Странно, но в моем случае ваш код работает хорошо. Может что-то не так с конфигурацией клиент / сервер?

Моя простая конфигурация сервера:

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;
}
Другие вопросы по тегам