首页 > 解决方案 > 在 netcore 3.1 中触发并忘记 SignalR 调用的简单方法

问题描述

我在 .net core 3.1 中有一个 Web 服务,它合理地大量使用了 SignalR。原始代码只调用调用 SignalR SendAsync 方法的方法,尽管可能有一些不必要的任务包装,但最终没有对与 SignalR 调用相关的任何 Task 执行任何操作:

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

这自然会导致很多“因为不等待这个电话......”。我想修改这个场景,所以它是“故意”触发并忘记(我们真的不在乎客户是否收到/遵守显示其横幅的指令,我们不想做任何有错误的事情,我们不想等待任何完成,我们也不关心如果服务器关闭是否有等待任务 - 我们只关心是否尽可能尝试消息)并删除这些特定用途的数百个警告

实现MSDN 上详述的后台工作队列功能是解决这个问题的方法吗?还是我想多了,我应该放弃任务?SendAsync 的文档说“不等待..”,现在一切正常,但我也很好奇这是否只是巧合,因为 SignalR 的东西比完成所需的时间更快/更轻对服务的请求;我们是否可以在某一天慢下来,以便我们发现 Web 服务请求在 SignalR 消息发生任何事情之前完成并结束,并且甚至不会尝试消息(即范围内的 hubmanager 是否可以由 DI 之前处理ShowBanner 被调用)

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

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

标签: c#asp.net-coreasync-awaitsignalrasp.net-core-3.1

解决方案


实现 MSDN 上详述的后台工作队列功能是解决这个问题的方法吗?还是我想多了,我应该放弃任务?

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

如果我这样改变,底层的消息传递是否仍然有效

是的。MethodAsync();是一样的_ = MethodAsync();。这两行都会调用该方法,然后忽略返回的任务。唯一的区别是显式丢弃 ( _),它本质上是您告诉编译器“是的,我知道这个任务没有等待,我是故意这样做的”。


推荐阅读