22

我刚刚开始探索 signalR,我希望能够将消息从服​​务器发送到所有客户端。

这是我的集线器

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using SignalR;
using SignalR.Hubs;
using SignalR.Hosting.Common;
using SignalR.Hosting.AspNet;
using System.Threading.Tasks;

namespace MvcApplication1
{
    public class Chat : Hub
    {
        public void Send(String message)
        {
            // Call the addMessage methods on all clients
            Clients.addMessage(message);
        }
    }
}

这是我的客户页面

      <script type="text/javascript">

         $(function () {

             //Proxy created on the fly
             var chat = $.connection.chat;

             // Declare a function on the chat hub so the server can invoke it
             chat.addMessage = function (message) {
                 $("#messages").append("<li>" + message + "</li>");
             };

             $("#broadcast").click(function () {
                 // call the chat method on the server
                 chat.send($("#msg").val());
             });

             $.connection.hub.start();
         });
    </script>


}



<input type="text" id="msg" />
        <input type="button" id="broadcast" value="broadcast" />

        <ul id="messages" class="round">


        </ul>

这一切都很完美,我可以在 2 个不同的浏览器之间“聊天”。

我要做的下一件事是从服务器向所有客户端发起一条消息。

所以我尝试了这个。

 using SignalR;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using System;
using System.Web.Routing;
using SignalR;
using SignalR.Hubs;

namespace MvcApplication1
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {            
            var aTimer = new System.Timers.Timer(1000);

            aTimer.Elapsed += aTimer_Elapsed;
            aTimer.Interval = 3000;
            aTimer.Enabled = true;

            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();
        }

        void aTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            var context = GlobalHost.ConnectionManager.GetHubContext<Chat>();
            context.Clients.Send("Hello");      
        }
    }
}

这似乎不起作用。计时器工作,“aTimer_Elapsed”事件处理程序每​​ 3 秒运行一次,但聊天中心上的“发送”方法从不运行。

有任何想法吗?

4

3 回答 3

37

我认为应该是

 void aTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        var context = GlobalHost.ConnectionManager.GetHubContext<Chat>();
        context.Clients.All.addMessage("Hello");      
    }

反而。使用 Send 您正在调用客户端用来调用服务器的方法...

于 2012-08-30T04:24:18.423 回答
9

如果您在被问到这个问题多年后遇到这个问题,并且您碰巧使用 .NET 5.0(或类似版本),那么以下内容可能会很有用,因为您可能正在使用不再提供该类的框架GlobalHost

.NET 5.0(和类似的)大量使用依赖注入(DI),在这里也使用它也就不足为奇了。以下示例代码显示了如何执行此操作。它不使用类GlobalHost

给定ChatHub类如下:

   public class ChatHub : Hub
   {
      public async Task SendMessage(string user, string message)
      {
         await Clients.All.SendAsync("ReceiveMessage", user, message).ConfigureAwait(false);
      }
   }

在类中Startup添加一行,如以下代码片段所示:

   public class Startup
   {
      // other code omitted for brevity

      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
      {
         // other code omitted for brevity

         app.UseEndpoints(endpoints =>
         {
            endpoints.MapControllers();
            endpoints.MapHub<ChatHub>("/chatHub"); // <====== add this ======
         });

         // other code omitted for brevity
      }
   }

然后在要向 SignalR 消息发送消息的控制器中,将 ChatHub 添加为依赖项。以下示例演示了如何为构造函数注入执行此操作:

   public class WeatherForecastController : ControllerBase
   {
      private readonly IHubContext<ChatHub> _hubContext;

      public WeatherForecastController(
         IHubContext<ChatHub> hubContext, // <============ add this ==========
         ILogger<WeatherForecastController> logger)
      {
         _hubContext = hubContext;
         _logger = logger;
      }
      
      [HttpGet]
      public virtual async Task<IEnumerable<WeatherForecastModel>> Get()
      {
         var rng = new Random();
         WeatherForecastModel[] weatherForecastModels = Enumerable.Range(1, 5).Select(index => new WeatherForecastModel
         {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)],
         }).ToArray();

         // Notify connected SignalR clients with some data:
         await _hubContext.Clients.All.SendAsync("ReceiveMessage", "the weatherman", $" The temperature will be {weatherForecastModels[0].TemperatureC}").ConfigureAwait(false);

         return weatherForecastModels;
      }

      // other code omitted for brevity
   }

这个例子还展示了如何在Get()方法中使用await _hubContext.Clients.All.SendAsync( ... )

有关详细信息,请参阅 Microsoft文档

于 2021-06-07T23:14:07.023 回答
1

是的,您必须将该行设置为:

void aTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        var context = GlobalHost.ConnectionManager.GetHubContext<Chat>();
        context.Clients.All.addMessage("Hello");      
    }

然而,这只是一半,仍然行不通。

在您的 Js 中,您需要编写:

$(function () {

//Proxy created on the fly
var chat = $.connection.chat;

// Declare a function on the chat hub so the server can invoke it
chat.client.addMessage = function (message) {
    $("#messages").append("<li>" + message + "</li>");
};

$("#broadcast").click(function () {
    // call the chat method on the server
    chat.client.addMessage($("#msg").val());
});

$.connection.hub.start();
});

我添加了chat.client这将添加服务器将调用的客户端集线器方法。

于 2016-09-28T09:44:06.723 回答