从ABP中的BackgroundWorker调用SignalR服务

时间:2018-02-26 02:23:36

标签: c# asp.net-core signalr backgroundworker aspnetboilerplate

我有一个BackgroundWorker,可以在5秒的间隔内向所有在线客户端广播:

DeactivationBackgroundWorker:

public class DeactivationBackgroundWorker : PeriodicBackgroundWorkerBase, ISingletonDependency
{
    private readonly IRepository<HitchRequest, long> _hitchRequestRepository;
    private readonly IHitchHub _hitchHub;

    public DeactivationBackgroundWorker(AbpTimer timer,
                                        IRepository<HitchRequest, long> hitchRequestRepository,
                                        IHitchHub hitchHub) : base(timer)
    {
        _hitchRequestRepository = hitchRequestRepository;
        Timer.Period = 5000;
        _hitchHub = hitchHub;
    }

    protected override async void DoWork()
    {
        await broadcastHitchRequestsAsync();
    }

    [UnitOfWork]
    private async Task broadcastHitchRequestsAsync() {
        var activeHitchRequests = _hitchRequestRepository.GetAllList(p => p.IsActive);

        foreach (var hitchRequest in activeHitchRequests)
        {
            await _hitchHub.RequestHitch(hitchRequest.Id);
        }

    }
}

IHitchHub:

public interface IHitchHub: ITransientDependency
{
    Task RequestHitch(long hitchId);
}

HitchHub:

public class HitchHub : AbpCommonHub, IHitchHub
{
    private readonly IOnlineClientManager _onlineClientManager;

    public HitchHub(IOnlineClientManager onlineClientManager, IClientInfoProvider clientInfoProvider): base(onlineClientManager, clientInfoProvider)
    {
        _onlineClientManager = onlineClientManager;
    }

    public async Task RequestHitch(long hitchId)
    {
        var onlineClients = _onlineClientManager.GetAllClients();
        foreach (var onlineClient in onlineClients) {

            var signalRClient = Clients.Client(onlineClient.ConnectionId);

            await signalRClient.SendAsync("receiveHitch", hitchId);
        }
    }
}

我不知道为什么HitchHub类中的 Clients 总是为null!我应该在哪里初始化它?

2 个答案:

答案 0 :(得分:2)

注入IHubContext<HitchHub>而不是IHitchHub

例如,请参阅ABP的SignalRRealTimeNotifier

相关问题:https://github.com/aspnet/SignalR/issues/182

答案 1 :(得分:0)

如果您使用Asp.net Core,请参阅:

Call SignalR Core Hub method from Controller

否则:

Hub不应由您自己或任何注入框架实例化

您必须使用ConnectionManager。对于您的代码,您应该使用:

GlobalHost.ConnectionManager.GetHubContext<HitchHub>().RequestHitch(hitchRequest.Id);

**有关Hub对象生存期的背景信息:**

https://docs.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-server

  

您没有实例化Hub类或调用它   来自您自己的代码的服务器上的方法;所有这一切都是为你完成的   SignalR Hubs管道。 SignalR创建Hub的新实例   class每次需要处理一个Hub操作时,例如a   客户端连接,断开连接或对服务器进行方法调用。

     

由于Hub类的实例是瞬态的,因此您无法使用它们   保持状态从一个方法调用到下一个。每一次   服务器接收来自客户端的方法调用,一个新的实例   Hub类处理消息。通过多重维持状态   连接和方法调用,使用一些其他方法,如a   数据库,或Hub类上的静态变量,或其他类   这不是来自Hub。如果您将数据保留在内存中,请使用   方法如Hub类上的静态变量,数据将是   应用程序域回收时丢失。

     

如果要根据自己运行的代码向客户端发送消息   在Hub类之外,您无法通过实例化Hub类来实现   例如,你可以通过获取SignalR的引用来实现   Hub类的上下文对象。有关更多信息,请参见如何   稍后调用客户端方法并从Hub类外部管理组   在这个主题中。

另见: https://docs.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-server#callfromoutsidehub