使用 SignalR 和 IProgress 接口的进度报告

Posted

技术标签:

【中文标题】使用 SignalR 和 IProgress 接口的进度报告【英文标题】:Progress report using SignalR and IProgress interface 【发布时间】:2014-10-27 09:46:42 【问题描述】:

我有一个 Hub 类,它有一个长时间运行的方法,我需要在它运行时显示一个进度条。

我阅读了this article,我认为可以在异步方法中使用 IProgress 接口来发送长时间运行的操作状态。

我这样写一个方法:

    public async Task<string> GetServerTime(IProgress<int> prog)
    
        await Task.Run(() => 
            for (int i = 0; i < 10; i++)
            
                prog.Report(i * 10);
                System.Threading.Thread.Sleep(200);
            
        );

        return DateTime.Now.ToString();
    

我尝试像这样调用该方法:

 var appHub = $.connection.appHub;
 $.connection.hub.start();
 appHub.server.getServerTime()
              .done(function (time) 
                    alert(time);
               );

但我不知道如何获得进度报告。

【问题讨论】:

您好,您必须在客户端的 IProgress 上创建实例并将其提供给 getServerTime 函数。然后你在客户端的 IProgress 上注册事件来做你的事情 谢谢,如何在客户端创建实例?! 【参考方案1】:

您可以use progress,如:

var appHub = $.connection.appHub;
$.connection.hub.start().done(function() 
  appHub.server.getServerTime()
    .progress(function (update)  alert(update); )
    .done(function (time)  alert(time); );
);

顺便说一句,在服务器端使用Task.Run 而不是CPU 绑定代码是没有意义的。您的服务器端代码也可以这样:

public string GetServerTime(IProgress<int> prog)

    for (int i = 0; i < 10; i++)
    
        prog.Report(i * 10);
        System.Threading.Thread.Sleep(200);
    

    return DateTime.Now.ToString();

您的服务器端方法只有在有真正的异步工作要做(通常是 I/O 绑定操作)时才应该是 async。作为一般规则,请避免在服务器端使用Task.Run

【讨论】:

起初我得到一个错误,说 progress 方法是一个未定义的类型,然后我将我正在使用的 jquery 1.6.4 替换为jquery 1.11.1,现在它可以工作了!谢谢@Stephen Cleary :) 与@Stephen Cleary 在 DamianEdwards/SignalR-2.x-demo github.com/DamianEdwards/SignalR-2.x-demo/blob/master/SignalR2x/… 的示例中推荐的想法相同 关于在 SignalR 集线器中的服务器上使用 async 的小提示。 SignalR documentation 中对此有非常明确的指导:使 Hub 方法异步避免在使用 WebSocket 传输时阻塞连接。当 Hub 方法同步执行且传输为 WebSocket 时,从同一客户端对 Hub 上的方法的后续调用将被阻止,直到 Hub 方法完成。【参考方案2】:

在您的 javascript 中添加以下客户端方法

 var appHub = $.connection.appHub;
  $.connection.hub.start();
  appHub.client.progress = function(progresspct) 
     // logic for whatever you want to do.
  ;

  appHub.server.getServerTime()
          .done(function (time) 
                alert(time);
           );

将你的服务器端代码修改为这个 -

    public async Task<string> GetServerTime(IProgress<int> prog)
   
    await Task.Run(() => 
        for (int i = 0; i < 10; i++)
        
            prog.Report(i * 10);
            // Call to your client side method.
            Clients.Client(Context.ConnectionId).progress(i);
            System.Threading.Thread.Sleep(200);
        
    );

    return DateTime.Now.ToString();

【讨论】:

以上是关于使用 SignalR 和 IProgress 接口的进度报告的主要内容,如果未能解决你的问题,请参考以下文章

c# 是不是可以在需要接口时提供 lambda?

.net core 3.0 Signalr - 02 使用强类型的Hub

.net core 3.0 Signalr - 02 使用强类型的Hub

将 SignalR 的 ITransportHeartbeat 添加到 Autofac

SignalR实现即时通讯技术,支持跨域

web api使用SignalR