【问题标题】:How to get the response of a HubProxy.Invoke call?如何获得 HubProxy.Invoke 调用的响应?
【发布时间】:2020-08-11 11:20:37
【问题描述】:

所以我有一个 C# client,它调用 SignalR hubmethod,集线器将返回 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;
}

我已经尝试用hubProxy.Invoke&lt;DateTime&gt;("GetCurrentServerTime").Result 替换await hubProxy.Invoke&lt;DateTime&gt;("GetCurrentServerTime"),但它的行为相同...

有没有人知道我做错了什么,导致死机警告被记录?

EDIT1:如果我在hubreturn DateTime.Now; 中放置一个断点,则断点被命中,hub 将其响应发送到client 没有问题。

【问题讨论】:

    标签: c# signalr deadlock signalr-hub signalr-client


    【解决方案1】:

    这很奇怪,但您的代码在我的情况下运行良好。也许客户端/服务器配置有问题?

    我的简单服务器配置:

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

    【讨论】:

      【解决方案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);
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-03
        相关资源
        最近更新 更多