RickStrahl / Westwind.AspnetCore.LiveReload

ASP.NET Core Live Reload Middleware that monitors file changes in your project and automatically reloads the browser's active page
Other
469 stars 42 forks source link

LiveReload middleware appears to be interfering with IHostApplicationLifetime application stopping callback #28

Closed Jamie411 closed 4 years ago

Jamie411 commented 4 years ago

I log a message at application shutdown in ASP.NET Core using the IHostApplicationLifetime interface. If I include the LiveReload middleware then the registered ApplicationStopped callback does not occur.

RickStrahl commented 4 years ago

Interesting.

Could be because the WebSocket is connected to the client and waiting for updates so the application is not going through the normal shut down routine because something is still running. It still shuts down through the physical process shut down but the shutdown event may not be firing.

That's conjecture, but that seems like a reasonable explanation.

Kind of a chicken and egg thing - the socket doesn't know the app wants to shut down and the app can't shut down because of the socket connection.

Not sure how to address that.

Any ideas?

RickStrahl commented 4 years ago

Ok... so took a closer look at this and the key is to use IHostApplicationLifetime (or IApplicationLifetime in 2.x) and inject that into the middleware. The object passed as ApplicationStopping cancellation tokens.

        #if !NETCORE2
            private IHostApplicationLifetime applicationLifetime;

            public LiveReloadMiddleware(RequestDelegate next,IHostApplicationLifetime lifeTime)
            {
                applicationLifetime = lifeTime;
                _next = next;
            }
        #else
            private IApplicationLifetime applicationLifetime;

            public LiveReloadMiddleware(RequestDelegate next, IApplicationLifetime lifeTime)
            {
                _next = next;
            }
        #endif

and the socket loop now does:

            while (webSocket.State.HasFlag(WebSocketState.Open))
            {
                try
                {
                    var received = await webSocket.ReceiveAsync(buffer, applicationLifetime.ApplicationStopping);
                }
                catch(Exception ex)
                {
                    break;
                }
            }

This seems to work. I added lifetime shutdown events to the 3.1 sample and the events are firing now:

            // Check for lifetime shutdown working with WebSocket active
            lifetime.ApplicationStopping.Register(() =>
            {
                Console.WriteLine("*** Application is shutting down...");
            }, true);

            lifetime.ApplicationStopped.Register(() =>
            {
                Console.WriteLine("*** Application is shut down...");
            }, true);
Jamie411 commented 4 years ago

Works great! Thanks