SignalR Core - 按顺序处理的请求



如果我通过一个连接到一个集线器的连接触发许多请求,它们将由服务器按顺序执行。所以没有平行主义的进步

我的中心有三种不同的方法

public Task Test1(string invokeId)
{
Clients.Caller.SendAsync("Hello", $"Test1: Before Delay ... InvokeID: {invokeId}");
Task.Delay(5000).Wait();
Clients.Caller.SendAsync("Hello", $"Test1: After Delay ...  InvokeID: {invokeId}");
return Task.CompletedTask;
}
public Task Test2(string invokeId)
{
Clients.Caller.SendAsync("Hello", $"Test2: Before Delay ... InvokeID: {invokeId}");
Task.Delay(2500).Wait();
Clients.Caller.SendAsync("Hello", $"Test2: After Delay ...  InvokeID: {invokeId}");
return Task.CompletedTask;
}
public Task Test3(string invokeId)
{
Clients.Caller.SendAsync("Hello", $"Test3: Before Delay ... InvokeID: {invokeId}");
Task.Delay(1250).Wait();
Clients.Caller.SendAsync("Hello", $"Test3: After Delay ...  InvokeID: {invokeId}");
return Task.CompletedTask;
}

我从客户端 .NET 应用程序循环调用它们

_connection.SendAsync("Test1", "1").ContinueWith(t => Console.WriteLine($"Test1: { t.Status }"));
_connection.SendAsync("Test2", "2").ContinueWith(t => Console.WriteLine($"Test2: { t.Status }"));
_connection.SendAsync("Test3", "3").ContinueWith(t => Console.WriteLine($"Test3: { t.Status }"));

遵循方法后

_connection.On("Hello", new Type[] { typeof(string) }, (parameters, state) =>
{
return Console.WriteLine((string)parameters[0]);
}, _connection);

我得到了以下输出

  • 测试1:运行到完成
  • 测试2:运行到完成
  • 测试3:运行到完成
  • 测试1:延迟之前...调用 ID:1
  • 测试1:延迟后... 调用 ID:1
  • 测试2:在延迟之前...调用 ID:2
  • 测试2:延迟后...调用 ID:2
  • 测试3:延迟之前...调用 ID:3
  • 测试3:延迟后... 调用 ID:3

如果你看看那个"测试2:延迟之前......InvokeID: 2" 将在 "Test1: After Delay ... 调用 ID:1"。似乎只允许同时使用一个 Hub 对象,无论所有三个调用都会立即返回"RanToCompletion",它们将一个接一个地执行。

它似乎非常具体,但我想构建一个应用程序,其中每个图形 WPF 对象将调用 SignalR 来检索内容。如果按顺序调用它们,我必须寻找另一种解决方案。

我错过了什么?

消息将由 SignalR Core 中的设计按顺序处理。

我搜索了 https://github.com/aspnet/SignalR 来源。在课堂上评论

Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher

功能

public override Task DispatchMessageAsync(HubConnectionContext connection, HubMessage hubMessage)
// Messages are dispatched sequentially and will stop other messages from being processed until they complete.
// Streaming methods will run sequentially until they start streaming, then they will fire-and-forget allowing other messages to run.

因此,您必须创建额外的类来处理您的操作,并且您的 Hub 必须立即返回。但是不要忘记将connectionId传递给你的类,这样你就可以使用connectionId进行回复,因为你的原始 Hub 会同时被销毁。

你没有指定,但如果我不得不猜测,我会说你正在本地测试它,这可能意味着你也在使用 IIS Express。IIS Express 是单线程的,因此多个并发请求将始终排队,因为需要一个线程来处理每个请求。

至于为什么你的RanToCompletion日志排在第一位,你没有提供任何实际记录的代码。结果,我不得不再次在黑暗中刺伤。很可能在记录该消息之前,您没有正确等待异步任务。然后,任务本身将在它们完成时运行并完成,但调用代码将继续移动并在此之前命中RanToCompletion日志记录行。

编辑

实际上,我现在明白RanToCompletion在哪里。它必须是t.Status的值。异步方法中的代码会立即返回,因为您没有等待内部的任何内容。包含的异步任务将启动,但在方法返回时尚未完成。然后,运行您的ContinueWithlambda,然后其中的任务完成并记录其他消息。

最新更新