首页 文章

如何在长时间运行的订阅线程中处理和恢复异常

提问于
浏览
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的连接将会停止 .

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

1 回答

  • 0

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

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

    请记住,catch会吞下所有内容,包括OutOfMemory异常,因此您需要进行一些完整性检查,如失败计数/延迟,这样您就不会立即重试 .

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

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

    您应该将其放入Windows服务中,以便在服务器启动时运行,如果必须与您的站点通信,则应通过WCF(双向)或通过访问Url(从服务推送到站点)来执行此操作 .

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

相关问题