异步命令和Task.WhenAny在StackExchange.Redis中等待之后的超时异常

时间:2014-08-29 11:40:10

标签: c# .net exception redis stackexchange.redis

我正在经历所谓的 Timeout执行HGET公司:产品:设置,inst:1,队列:8,qu = 0,qs = 8,qc = 0,wr = 0/0,in = 79/1 超时异常。

这很奇怪,因为相同的Redis实例和同一台机器存储数据,但它是一个抛出此异常的特定应用程序。 更新:实际上,同一个应用程序,上面一行从Redis接收数据。问题出在HGET

此外,我已将多路复用器配置的超时时间增加到6秒,但没有运气。

此外,我已检查IDatabase实例的IsConnected值为true

如何解释这些错误消息以及整个超时背后的问题是什么?

一些背景......

当某些代码部分获得数据库(即multiplexer.GetDatabase())时,我已成功修复了更改的问题。

虽然多路复用器具有每个AppDomain的实例,如StackExchange.Redis文档中所述,但许多控制组件的反转都在他们自己的代码中创建了许多IDatabase实例。也就是说,IDatabase实例不会被共享。

实际代码正在执行ListRightPopLeftPush,之后,它实例化控件组件的反转,该组件在组件实例化期间读取哈希键。如果在执行所谓的ListRightPopLeftPush之前实例化整个组件,那么整个HashGet将不会抛出超时异常。

即使从其他ListRightPopLeftPush实例执行IDatabase,它似乎也会在执行读取操作时在下一个IDatabase实例中产生某种问题。

无论如何,我的修复没有回答这个问题。我刚刚添加了更详细的信息,让我们找到问题所在和自己的解决方案。

更新

无论如何,上面的“修复”不会修复对Redis的进一步读取访问。我在进一步的调用中得到了相同的超时异常。现在in例程中的60/1参数在异常消息中显示为{{1}}。

1 个答案:

答案 0 :(得分:6)

基于long discussion in chat,以及大量的挖掘,看起来在一些模糊的场景中,当我们做.TrySetResult之类的事情时,TPL正在劫持专用的读者线程(我们经常这样做) )。如果您进行同步调用,这会导致即时死锁,因为如果忙于等待任务完成(它本身只能完成),它就不可能处理任何套接字数据。我们实际上有code in place specifically to prevent this,但看起来实际上强制的解决方法在其他一些场景中发生。哪个......太可怕了。我会看到我能找到的东西。但基本上,问题是当前,在一些有限的场景中,TaskCompletionSource.TrySetResult正在赋予TPL运行同步延续的权力。这包括Task.WhenAny