在 net core 3.1 中触发和忘记 SignalR 调用的简单方法

Simple way to fire-and-forget SignalR calls in netcore 3.1

我在 .net core 3.1 中有一个 Web 服务,它相当大量地使用了 SignalR。原始代码只调用调用 SignalR SendAsync 方法的方法,虽然可能有一些不必要的任务包装,但最终与 SignalR 调用相关的任何任务都没有完成:

    //in the hub manager
    public async Task ShowBanner(string group)
    {
        await _signalrHubContext.Clients.Group(group).SendAsync("showBanner");
    }

    //in the controller
    [HttpGet("Show/Banner")]
    public async Task<ActionResult> ShowBanner()
    {
        try {
            //some other await-necessary db stuff here
            await dbcontext.Blah....;

            somehubmanager.ShowBanner(); //because this call is not awaited...

            return Ok();
        }
        catch (Exception e)
        {
            return StatusCode((int)HttpStatusCode.InternalServerError, e.Message);
        }
    }

这自然会导致很多 "because this call is not awaited..."。我想修改这个场景,所以它 "deliberately" 触发后忘记(我们真的不关心客户端是否 receives/obeys 显示其横幅的指令,我们不想做任何事情有错误,我们不想等待任何完成,我们也不关心如果服务器关闭是否有等待任务 - 我们只真正关心如果可能会尝试消息)并删除这些消息的数百个警告特殊用途

实现后台工作队列功能 detailed on MSDN 是否可行?还是我想太多了,我应该放弃这个任务? SendAsync 的文档说 "doesn't wait for..",现在一切正常,但我也很好奇这是否纯属巧合,因为 SignalR 的东西 quicker/more 比完成请求所需的时间轻到服务;我们是否可以有一天慢下来,这样我们发现 Web 服务请求在 SignalR 消息传递发生任何事情之前完成并结束并且消息甚至不会被尝试(即范围内的 hubmanager 是否可以在 DI 之前处理) ShowBanner 被调用)

我只是不确定在 SignalR 的特定上下文中我必须 "take care" 任务多长时间;如果我这样改变,底层消息传递是否仍然有效:

    public Task ShowBanner(string group)
    {
        return _signalrHubContext.Clients.Group(group).SendAsync("showBanner");
    }

    [HttpGet("Show/Banner")]
    public async Task<ActionResult> ShowBanner()
    {
        try {
            //some other await-necessary db stuff here
            await dbcontext.Blah....;

            _ = somehubmanager.ShowBanner();

            return Ok();
        }
        catch (Exception e)
        {
            return StatusCode((int)HttpStatusCode.InternalServerError, e.Message);
        }
    }

Would implementing the background work queue functonality detailed on MSDN be the way to go for this? Or am I overthinking it, and I should just discard the Task?

后台队列会在 运行 处为您提供 "best effort" 代码。后台队列为您提供了一种与托管进程交互的方式,并会在可能的情况下延迟关闭以 运行 代码。也就是说,如果它不是那么重要,则放弃任务会更容易。

would the underlying messaging still work the same if I changed things thus

是的。 MethodAsync();_ = MethodAsync(); 相同。这两行都将调用该方法,然后忽略返回的任务。唯一的区别是显式丢弃 (_),这实际上是您告诉编译器 "yes, I know this task isn't awaited, and I'm doing it on purpose".