Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# StackExchange.Redis阻止pop设计_C#_Stackexchange.redis - Fatal编程技术网

C# StackExchange.Redis阻止pop设计

C# StackExchange.Redis阻止pop设计,c#,stackexchange.redis,C#,Stackexchange.redis,因此,我们有一个使用ServiceStack.Redis的现有帮助程序库,目前正试图将其与StackExchange.Redis交换。我们使用BlockingPop(BLPOP),但自从StackExchange.Redis不支持它以来。我们按如下方式实施它 public static void Push(string Qname, string val) { IDatabase db = redis.GetDatabase(); db.ListLeftPush(Qname, v

因此,我们有一个使用ServiceStack.Redis的现有帮助程序库,目前正试图将其与StackExchange.Redis交换。我们使用BlockingPop(BLPOP),但自从StackExchange.Redis不支持它以来。我们按如下方式实施它

public static void Push(string Qname, string val)
{
    IDatabase db = redis.GetDatabase();
    db.ListLeftPush(Qname, val);
    ISubscriber sub = redis.GetSubscriber();
    sub.Publish(Qname + "_msg", "1");
}
和带有阻塞选项的Pop,如下所示:

    public static string Pop(string Qname, 
    bool block_until_available = false,int timeout_secs=0)
{   
    IDatabase db = redis.GetDatabase();            
    var popped = db.ListRightPop(Qname);
    if (popped.IsNull)
    {
        if (block_until_available == false)
            return null;
    }
    else
        return popped;

    //wait for an item to be pushed in.
    ISubscriber sub = redis.GetSubscriber();
    AutoResetEvent autoEvent = new AutoResetEvent(false);
    string obj = null;
    Task.Run(() =>
    {
        sub.Subscribe(Qname + "_msg", (channel, message) =>
        {
            popped = db.ListRightPop(Qname);
            if (!popped.IsNull)
            {
                obj = popped;
                sub.Unsubscribe(Qname + "_msg");
                autoEvent.Set();
            }
        });
    });
    if (timeout_secs > 0)
        autoEvent.WaitOne(timeout_secs * 1000);
    else
        autoEvent.WaitOne();
    return obj;
}
你们都看到这种方法有什么明显的问题吗

而且,我很快就遇到了以下错误。我增加了同步超时时间。希望这能解决问题

System.TimeoutException: Timeout performing RPOP DL_PROD, 
inst: 0, mgr: ProcessReadQueue, err: never, queue: 0, qu: 0, qs: 0, qc: 0, 
wr: 0, wq: 0, in: 0, ar: 1, IOCP: (Busy=0,Free=1000,Min=8,Max=1000), 
WORKER: (Busy=2,Free=32765,Min=8,Max=32767), 
clientName: CD147RE1 at 
StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T]
(Message message, ResultProcessor`1 processor, ServerEndPoint server) 

这里没有RPOP应该超时的具体原因,除非它与带宽相关(巨大的有效负载)。这个错误看起来与IMO的问题无关。这个方法很难看,但。。。好吧,这可能有用。不需要使用Task。但请在此处运行。我认为,这种方法的一个问题是它不能同时正常工作。它似乎取消了该频道/连接的所有代理,而不仅仅是一个。自我取消订阅是可能的,但坦率地说,我想知道是否只需要一个自动重置事件和一个订阅就更容易了,如果在您等待时有一条消息打开了大门:太好了


自退订代理的一般模式基本上是:

YourDelegateType handler = null;
handler = (args) => {
    DoTheThing();
    UnSubscribe(handler);
};
Subscribe(handler);

这使用词汇捕获变量的乐趣来提供对委托内部委托实例的访问,这意味着委托可以将自身传递给unsubscribe方法。上面显示的模式应该适用于所有基于委托的回调场景-包括regulate事件和类似SE.Redis发布/订阅处理程序的事情。

我不知道为什么会被否决-问题是,我在这个解决方案中遇到了多个问题。请极其小心地使用此解决方案。不,有效负载很小。Redis几乎没有被利用。我唯一能想到的就是网络。取消订阅和单一订阅的想法很有道理。我会调查的。我如何自我退订?@coderguy123更复杂;将在编辑中显示我遇到的另一个问题,但有时(非常罕见)从“推”操作到频道的信号丢失,所以消费者永远不会弹出它。消息仍在队列中。您认为我需要在leftpush和publish之间添加一个时间延迟吗?这些都不是Fireandforget模式,所以我认为应该是同步的,不应该有什么关系?@coderguy123如果没有复制,很难知道,但这通常是一个时间问题(特别是在发布/订阅与命令连接之间)-因此我怀疑单个订阅会更稳定(因为它消除了时间问题)。无论哪种方式:设置超时/重试都可能是一个好主意。