C# 如何在信号集线器上缓冲消息并在正确的客户端出现时发送它们?

C# 如何在信号集线器上缓冲消息并在正确的客户端出现时发送它们?,c#,asp.net-core,signalr,asp.net-core-signalr,C#,Asp.net Core,Signalr,Asp.net Core Signalr,我有两种类型的客户端连接我的信号服务器(ASP.NET核心)。其中一些是发送者,一些是接收者。我需要将消息从发送者路由到接收者,这不是一个问题,但是当没有接收者时,我需要以某种方式缓冲消息并且不丢失它们(在某种单例类中,最好的可能是ConcurrentQueue),但是当第一个接收者连接时,消息缓冲区需要开始出列。哪种方法是最好的 我创建了一个单件类,将ConcurrentQueue集合包装起来,并在那个里对消息进行排队和出列。另外,我还有一个单独的单例类,它保存接收方连接ID的集合。我在第二个

我有两种类型的客户端连接我的信号服务器(ASP.NET核心)。其中一些是发送者,一些是接收者。我需要将消息从发送者路由到接收者,这不是一个问题,但是当没有接收者时,我需要以某种方式缓冲消息并且不丢失它们(在某种单例类中,最好的可能是ConcurrentQueue),但是当第一个接收者连接时,消息缓冲区需要开始出列。哪种方法是最好的

我创建了一个单件类,将ConcurrentQueue集合包装起来,并在那个里对消息进行排队和出列。另外,我还有一个单独的单例类,它保存接收方连接ID的集合。我在第二个类中实现了event,当第一个接收器在接收器列表为空后连接时触发事件,但这可能不是一个好方法,我不知道如何在Hub中使用id,因为信号器Hub有多个实例。
第二种方法是将persistence类标记为controller,并将ContextHub和message buffer注入该类中,然后将buffer从该类中退出队列,并直接将消息发送给接收者???

如果我理解得很清楚,您希望通过在某些IHostedService中使用类似同步调用的方法来延迟信号器消息发送。以下是我迄今为止所取得的成就

  • 使用包含可调用操作委托的ConcurrentQueue来处理并发集线器调用的方法是正确的。正如你提到的,它必须作为一个单体注入
因此这里的
队列
类:

public class Queues {
    public ConcurrentQueue<Action<IHubContext<MyHub, IMyEvents>>> MessagesQueue { get; set; }
}
public class DeferredMessageSender {
    Queues queues;
    IHubContext<MyHub, IMyEvents> hub;

    public DeferredMessageSender(Queues queues, IHubContext<MyHub, IMyEvents> hub) {
        this.queues = queues;
        this.hub = hub;
    }

    public void GlobalSend() {
        while(queues.MessagesQueue.TryDequeue(out var evt)) {
            evt.Invoke(hub);
        }
    }
}
  • 现在,使用一种简单的方法,该代码将触发以延迟方式发送消息。(在工作中,计时器确保有规律的节奏,该类是
    IHostedService
    ,但此处不显示)。这个类必须作为单例注入
这里的
DeferredMessageSender
类:

public class Queues {
    public ConcurrentQueue<Action<IHubContext<MyHub, IMyEvents>>> MessagesQueue { get; set; }
}
public class DeferredMessageSender {
    Queues queues;
    IHubContext<MyHub, IMyEvents> hub;

    public DeferredMessageSender(Queues queues, IHubContext<MyHub, IMyEvents> hub) {
        this.queues = queues;
        this.hub = hub;
    }

    public void GlobalSend() {
        while(queues.MessagesQueue.TryDequeue(out var evt)) {
            evt.Invoke(hub);
        }
    }
}
公共类延迟MessageSender{
排队;
IHubContext中心;
公共延迟消息发送者(队列、IHubContext中心){
this.queues=队列;
this.hub=hub;
}
public void GlobalSend(){
while(queues.messagesquee.TryDequeue(out-var-evt)){
evt.Invoke(集线器);
}
}
}

希望有帮助。

我如何才能将IHubContext和其他两个单例类正确地注入到我的控制器类中?我如何知道某些客户端没有收到消息,以便稍后重试?我在客户端上有消息队列,但我不知道如何确保在重新连接后将丢失的消息传递给他们。我找不到任何资源,你知道怎么做吗?这很棘手。我们正在使用一种变通方法,它包括将我们发送的每一条消息推送到一个带有timestamp1的滚动列表中(以限制缓冲消息的数量)。当客户机第一次断开连接时,他会在它发生时获得时间戳,然后他会尝试重新连接,直到它成功做到这一点。然后它发送一个“getmissedmessage(timestamp)”,因此服务器从滚动列表中获取该时间戳之前的消息,并仅将它们重新发送给该客户端。