1

So I have a C# client which invokes a method of the SignalR hub, where the hub will return a DateTime.

But the behaviour I am now experiencing, is that the client gets stuck at the HubProxy.Invoke which ends up on logging the following:

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

This is the code of the 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;
}

This is the code of the Hub:

public DateTime GetCurrentServerTime()
{
    return DateTime.Now;
}

I already tried replacing await hubProxy.Invoke<DateTime>("GetCurrentServerTime") with hubProxy.Invoke<DateTime>("GetCurrentServerTime").Result but it behaves the same...

Does anyone have an idea what I'm doing wrong, causing the deadling warning to be logged?

EDIT1: If I put a breakpoint in the return DateTime.Now; of the hub, the breakpoint is hit, and the hub has no problem sending its response to the client.

Koen
  • 17
  • 4

2 Answers2

0

It's strange, but your code works well in my case. Maybe there something wrong with client / server configuration?

My simple server configuration:

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

Client configuration:

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 hub:

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

Was able to fix it myself by making it not waited upon:

_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);
});
Koen
  • 17
  • 4