我正在编写ASP.NET Core 2.2 C#Web应用程序,该应用程序使用SignalR在Web浏览器中从JavaScript接听电话。在服务器端,我这样初始化信号:
public static void ConfigureServices(IServiceCollection services)
{
...
// Use SignalR
services.AddSignalR(o =>
{
o.EnableDetailedErrors = true;
});
}
和
public static void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
// Route to SignalR hubs
app.UseSignalR(routes =>
{
routes.MapHub<ClientProxySignalR>("/clienthub");
});
...
}
我的Signalr Hub类具有这样的方法:
public class ClientProxySignalR : Hub
{
...
public async Task<IEnumerable<TagDescriptor>> GetRealtimeTags(string project)
{
return await _requestRouter.GetRealtimeTags(project).ConfigureAwait(false);
}
...
}
和客户端:
var connection = new signalR.HubConnectionBuilder()
.withUrl("/clienthub")
.configureLogging(signalR.LogLevel.Information)
.build();
connection.start().then(function () {
...
// Enable buttons & stuff so you can click
...
}
document.getElementById("tagGetter").addEventListener("click", function (event) {
connection.invoke("GetRealtimeTags", "Project1").then(data => {
...
// use data
...
}
}
这一切都起作用,并且确实不同步地工作。因此,如果我单击" taggetter"按钮,它会在集线器上调用" getRealTimetags"方法,并在数据返回时调用"然后"部分。的确,如果这需要一段时间才能运行,并且我再次单击" taggetter"按钮,同时,它会再次访问。>
但是...这是问题发生的地方。尽管第二个呼叫是在JavaScript中进行的,但直到第一个呼叫完成之前,它不会触发我的SignalR Hub类中的相应方法。这与我对应该发生的事情的理解不符。我以为SignalR Hub方法回到服务器的每个调用都会导致创建集线器类的新实例来处理呼叫。相反,第一个电话似乎正在阻止第二个。
如果我在JavaScript代码中创建了两个不同的连接,那么我可以同时对其进行两个同时调用,而不会阻止另一个。但是我知道这不是做这项工作的正确方法。
所以我的问题是:在这种情况下我做错了什么?
这是通过设计Websocket的设计,以确保以确切顺序传递消息。
您可以参考此信息:https://hpbn.co/websocket/
引用:
上一个示例尝试将应用程序更新发送到 服务器,但前提是从以前的消息中排出的 客户的缓冲区。为什么要去这样的支票?所有Websocket消息 按确切顺序交付的顺序 客户。结果,大量的排队消息,甚至是 单个大消息,将延迟在后面排队的消息的传递 它 - 线路阻塞!
他们还建议解决方法:
要解决此问题,该应用程序可以拆分大消息 成较小的块,仔细监视缓冲的山值 避免在线封锁,甚至实施自己的优先级队列 为了等待消息,而不是盲目地排队 插座。
有趣的问题。
我认为应该禁用该按钮并首次单击加载图标。但是,也许您的UI可以一次加载多个项目。只是想一秒钟,我们可能会有X-y问题。
无论如何,要回答您的问题:
您可以轻松解决此问题的一种方法是将"获取和发送"数据的过程中的"请求"数据的过程分解给用户。
- 不要等待
GetRealtimeTags
,而是启动一个背景任务,以指出呼叫者的连接ID - 从
GetRealtimeTags
返回 - 一旦结果在后台任务中准备就绪后,请调用新的
RealtimeTagsReady
方法,该方法将使用较早保留的连接ID调用JavaScript客户端
让我知道这是否有帮助。