0

我在几个 ASP.NET MVC 应用程序中使用 ServiceStack.Redis,以促进这些应用程序之间的基本消息传递。在一个应用程序中,我有一个类来设置订阅并处理应用程序感兴趣的任何消息,例如:

public MessageBus(IRedisClientsManager redisClientsManager)
{
    Thread subscriptionThread = new Thread(() => {
        try
        {
            using (var redisClient = redisClientsManager.GetClient())
            using (var subscription = redisClient.CreateSubscription())
            {
                subscription.OnMessage = (channel, message) =>
                {
                    handleMessage(message);
                };
                subscription.SubscribeToChannels("MyChannel");
            }
        }
        catch (Exception ex)
        {
            ErrorLog.GetDefault(null).Log(new Error(ex));
        }
    });
    subscriptionThread.Start();
}

由于“SubscribeToChannels”被阻塞,我让它在一个单独的线程中运行。我希望该线程在 MVC 应用程序运行的整个过程中保持活动状态,并且我担心如果发生任何类型的异常,该线程将会死掉,或者与 Redis 的连接将停止。

我的问题是:是否有任何示例说明如何从订阅打开时可能发生的异常(连接失败、超时等)中恢复?

4

1 回答 1

0

关于杀死线程的异常,请使用长时间运行的循环:

while(!ShutdownRequested) {
    try{...}
    catch(Exception e) {/*Log and probably do some rate-limiting in case of terminal issue*/}
}

请记住,catch 会吞噬一切,包括 OutOfMemory 异常,因此您需要进行一些健全性检查,例如失败计数/延迟,这样您就不会总是立即重试。

不要忘记您可以保留对来自父级的后台线程的引用并检查ThreadState

至于在 ASP 中托管,这是一个坏主意(请参阅此答案)。当工作池被回收(最终会发生)时,线程将死亡并且在请求新页面之前不会重新生成(最早)。

您应该将其放入 Windows 服务中,以便它在服务器启动时运行,并且如果它必须与您的站点通信,它应该通过 WCF(2 路)或通过点击 Url(从服务推送到站点)来执行此操作。

这样,它只会在服务停止时死掉(希望只是重新启动)。

于 2014-05-21T00:23:21.707 回答