如果我通过一个连接向一个集线器发出许多请求,它们将由服务器按顺序执行。因此没有平行主义的进步
我的中心有三种不同的方法
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 }"));
以下On方法
_connection.On("Hello", new Type[] { typeof(string) }, (parameters, state) =>
{
return Console.WriteLine((string)parameters[0]);
}, _connection);
我得到了以下OUTPUT
如果你看一下“Test2:Before Delay ... InvokeID:2”将在“Test1:After Delay ... InvokeID: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
的价值。你的异步方法中的代码会立即返回,因为你不是在等待任何内部的东西。包含的异步任务已启动,但在方法返回时尚未完成。然后,运行你的ContinueWith
lambda,然后完成内部的任务并记录其他消息。