我在几个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的连接将会停止。
我的问题是:是否有任何关于如何从订阅开放时可能发生的异常(连接失败,超时等)中恢复的示例?
答案 0 :(得分:0)
关于杀死线程的异常,请使用长时间运行的循环:
while(!ShutdownRequested) {
try{...}
catch(Exception e) {/*Log and probably do some rate-limiting in case of terminal issue*/}
}
请记住,捕获将吞噬所有内容,包括OutOfMemory异常,因此您需要进行一些完整性检查,例如失败计数/延迟,以便您不必立即重试。
不要忘记你可以保留对父母的背景线索的引用,并检查ThreadState。
至于在ASP中托管,这是一个坏主意(参见this answer)。当工作池被回收(最终会发生)时,线程将会死亡并且不会重新生成,直到请求新页面为止(最早)。
你应该把它放到一个Windows服务中,以便它在服务器启动时运行,如果它必须与你的站点通信,它应该通过WCF(双向)或通过点击一个Url(从服务推送到位点)。
这样,它只会在服务停止时死亡(希望只重新启动)。