ASP.net HttpHandler长时间运行ProcessRequest并没有结束App回收

时间:2011-10-12 22:24:28

标签: c# asp.net httphandler

我试图在ASP.net中实现HttpStreaming彗星推送服务器。我正在实现一个IHttpAsyncHandler,它保留一个http请求并定期向连接的客户端发送消息。与客户的连接可以保持打开很长时间(比方说30分钟)。我遇到的问题是,由于我很长时间没有结束请求,因此处理程序技术仍在运行。因此,当应用程序池回收或结束时,我的asp.net应用程序不会优雅地结束。意思是,Application_End永远不会在Global.asax中调用,因为它在调用之前等待所有处理程序完成。我的处理程序尚未完成,因为它正在保留请求。最终,该应用程序刚刚被IIS杀死。

这里有一个无限运行的示例HttpHandler,直到某些东西告诉它停止。

public class StreamingSocketHandler3 : IHttpHandler
{
    private static readonly AppDomainShutdown Instance = AppDomainShutdown.Instance;

    public void ProcessRequest(HttpContext context)
    {

        long c = 1;
        bool stop = false;
        Instance.OnStop += delegate()
        {
            stop = true;
        };

        while (!stop)
        {
            LogThis.Log.LogThis("loop: " + c, LogThis.eloglevel.debug);
            c++;
            System.Threading.Thread.Sleep(1000);
        }
    }

    public bool IsReusable
    {
        get
        {
            return true;
        }
    }
}

如果客户端连接到此处理程序,然后我停止了应用程序池,则Web应用程序不会结束,直到该应用程序稍后被IIS完全杀死。

这个问题的明显答案是听取某种应用程序结束事件然后结束请求。我无法挂钩到Global.asax Application_end,因为在处理程序结束之前它不会被调用。以下博客文章(link)提供了一些其他选择(请参阅帖子末尾的q5)。我已经尝试过AppDomain.DomainUnload事件建议没有运气。我也尝试过建议的IRegisteredObject接口。这也不起作用。我构建了以下类来实现IRegisteredObject以进行测试。

public sealed class AppDomainShutdown : IRegisteredObject
{
    public event Action OnStop;

    // Singleton reference
    public static readonly AppDomainShutdown Instance = new AppDomainShutdown();

    // Singleton private Constructor
    private AppDomainShutdown()
    {
        // Register the object
        HostingEnvironment.RegisterObject(this);
    }

    public void Stop(bool immediate)
    {
        // Whats it want us to do?
        if (!immediate)
        {
            // Do some code to handle graceful
            // if OK
            LogThis.Log.LogThis("Not Immediate Stop called", LogThis.eloglevel.debug);
            OnStop();
            HostingEnvironment.UnregisterObject(this);
        }
        else
        {
            // Do some code to force down (THREAD.ABORT)
            // Mandatory
            LogThis.Log.LogThis("Immediate Stop called", LogThis.eloglevel.debug);
            OnStop();
            HostingEnvironment.UnregisterObject(this);
        }
    }
}

如果我在没有处理程序启动的情况下从Global.asax调用此类,我会按预期获得应用程序停止通知。但是,在HttpHandler中放置相同的调用(请参阅处理程序代码),OnStop事件永远不会触发。

令人沮丧的是,我在网上看到了几个论坛帖子,帖子有我的确切问题,据说海报能够实现IRegisteredObject并结束HttpRequest,以便应用程序可以关闭。

请注意,我提供的HttpHandler代码仅用于测试我可以结束ProcessRequest方法以响应应用程序结束。

0 个答案:

没有答案