SignalR Core-顺序处理的请求

时间:2018-08-29 14:13:49

标签: asp.net-core-signalr

如果我通过与一个集线器的一个连接触发许多请求,它们将由服务器顺序执行。因此没有并行性的进步

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

    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);

我关注了输出

  • Test1:RanToCompletion
  • Test2:RanToCompletion
  • Test3:RanToCompletion
  • Test1:延迟之前... InvokeID:1
  • Test1:延迟后... InvokeID:1
  • Test2:延迟之前... InvokeID:2
  • Test2:延迟后... InvokeID:2
  • Test3:延迟之前... InvokeID:3
  • Test3:延迟后... InvokeID:3

如果您看到“ Test2:延迟前... InvokeID:2”将在“ Test1:延迟后... InvokeID:1”之后直接调用。似乎同一时间只允许一个Hub对象,无论所有三个调用都将立即返回“ RanToCompletion”,它们都将一个接一个地执行。

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

我想念什么?

2 个答案:

答案 0 :(得分:1)

消息将根据设计在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.

因此,您必须创建其他类来处理您的操作,并且集线器必须立即返回。但是不要忘记将 connectionId 传递给您的班级,因此您可以使用 connectionId 进行回复,因为您的原始集线器同时已被破坏。

答案 1 :(得分:0)

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

至于为什么您的RanToCompletion日志排在第一位,您尚未提供任何实际记录该日志的代码。结果,我不得不再次在黑暗中刺伤。很可能在记录该消息之前,您没有适当地等待异步任务。任务本身将在运行完成后立即运行并完成,但是调用代码会继续运行并在发生之前命中您的RanToCompletion记录行。

编辑

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