【发布时间】:2019-01-28 19:03:53
【问题描述】:
我是 SignalR 的新手。我正在尝试设置一个 Asp.Net Core WebAPI,以便其他客户端可以使用 SignalR 连接到它并获取实时数据。 我的 Hub 课程是:
public class TimeHub : Hub
{
public async Task UpdateTime(string message)
{
await Clients.All.SendAsync("ReceiveMessage", message);
}
}
我有一个接力班如下:
public class TimeRelay : ITimeRelay
{
private readonly IHubContext<TimeHub> _timeHubContext;
public TimeRelay(IHubContext<TimeHub> context)
{
_timeHubContext = context;
Task.Factory.StartNew(async () =>
{
while (true)
{
await context.Clients.All.SendAsync("UpdateTime", DateTime.Now.ToShortDateString());
Thread.Sleep(2000);
}
});
}
}
启动类:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSignalR();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseHttpsRedirection();
app.UseSignalR((x) =>
{
x.MapHub<TimeHub>("/timeHub");
});
app.UseMvc();
}
客户端是一个控制台应用,代码是:
class Program
{
static Action<string> OnReceivedAction = OnReceived;
static void Main(string[] args)
{
Connect();
Console.ReadLine();
}
private static async void Connect()
{
var hubConnectionBuilder = new HubConnectionBuilder();
var hubConnection = hubConnectionBuilder.WithUrl("http://localhost:60211/timeHub").Build();
await hubConnection.StartAsync();
var on = hubConnection.On("ReceiveMessage", OnReceivedAction);
Console.ReadLine();
on.Dispose();
await hubConnection.StopAsync();
}
static void OnReceived(string message)
{
System.Console.WriteLine($"{message}");
}
}
我尝试调试应用程序。客户端成功连接到TimeHub。当客户端连接时,Clients.All 中的连接数从 0 变为 1。但是,当await context.Clients.All.SendAsync("UpdateTime", DateTime.Now.ToShortDateString());被执行时,TimeHub中的UpdateTime函数没有被执行,客户端也没有收到任何消息。
我尝试在TimeRelay 类的Clients.All.SendAsync 中使用"UpdateTime"、"SendMessage" 和"ReceiveMessage" 作为方法。没有任何效果。有人可以指出我在这方面的错误。
【问题讨论】:
-
你在哪里打电话给
TimeRelay?TimeRelay和TimeHub在同一个项目中吗?您对TimeRelay的预期结果是什么?一般来说,Clients.All.SendAsync,它用于调用客户端方法而不是服务器方法。如果您更喜欢从TimeRelay调用TimeHub.UpdateTime,请尝试注册TimeHub类并调用TimeHub.UpdateTime(),或者直接从TimeRelay调用ReceiveMessage通过await context.Clients.All.SendAsync("ReceiveMessage", DateTime.Now.ToShortDateString());。 -
现在,我从 HomeController 调用
TimeRelay。来回答你。是的,TimeRelay和TimeHub在同一个项目中。我会尝试注册TimeHub。另外,我确实在Clients.All.SendAsync中尝试过"ReceiveMessage",但没有成功。 -
我想知道在控制器动作中启动一个新线程是否合理。我在控制器
index操作中调用TimeHub进行了测试,它仅适用于第二个请求。我会继续检查这种行为。 -
@TaoZhou 谢谢。在 Controller 中启动线程只是一种临时方法。坦率地说,目前,我无法想出另一种方式来启动它。首先,我试图让 SignalR 先工作。
-
@AlenAlex 就像上面评论中提到的
Clients.All.SendAsync将直接调用客户端方法。然而,上面还提到了手动实例化集线器和调用集线器方法。这是非常错误的,永远不要获取集线器实例,因为它不会设置正确的属性。如果您想从控制器调用“集线器方法”,则需要重构代码,以便集线器方法和控制器调用相同的代码,然后您可以从集线器和控制器使用Clients.All.SendAsync发送到客户端使用重构方法返回的数据。
标签: c# asp.net-core .net-core signalr asp.net-core-webapi