停止自托管owin服务器时完成当前请求

Luk*_*rkl 5 .net c# self-hosting owin katana

我有OWIN服务器作为控制台应用程序的一部分.你可以在这里看到主要方法:

class Program
{
    public static ManualResetEventSlim StopSwitch = new ManualResetEventSlim();

    static void Main(string[] args)
    {
        Console.CancelKeyPress += (s, a) =>
        {
            a.Cancel = true;
            StopSwitch.Set();
        };

        using (WebApp.Start<Startup>("http://+:8080/"))
        {
            Console.WriteLine("Server is running...");
            Console.WriteLine("Press CTRL+C to stop it.");
            StopSwitch.Wait();
            Console.WriteLine("Server is stopping...");
        }

        Console.ReadKey();
        Console.WriteLine("Server stopped. Press any key to close app...");
    }
}
Run Code Online (Sandbox Code Playgroud)

当请求的处理稍微长一点并且同时用户按下CTRL + C以停止应用程序时,立即停止请求处理并且不发送响应.是否有可能改变这种行为?我想拒绝所有新请求,但要等到当前正在处理的请求完成并在此之后停止服务器.

我最初的想法是创建OWIN中间件,它将跟踪当前正在处理的请求并推迟停止操作直到一切都完成.中间件还会在停止阶段将所有请求短路.但这个解决方案对我来说听起来不太好.

Luk*_*rkl 4

我以建议的中间件方法结束:

public class ShutDownMiddleware
{
    private readonly Func<IDictionary<string, object>, Task> next;
    private static int requestCount = 0;
    private static bool shutDownStateOn = false;

    public static void ShutDown()
    {
        shutDownStateOn = true;
    }

    public static int GetRequestCount()
    {
        return requestCount;
    }

    public ShutDownMiddleware(Func<IDictionary<string, object>, Task> next)
    {
        this.next = next;
    }

    public async Task Invoke(IDictionary<string, object> environment)
    {
        if (shutDownStateOn)
        {
            environment["owin.ResponseStatusCode"] = HttpStatusCode.ServiceUnavailable;
            return;
        }

        Interlocked.Increment(ref requestCount);
        try
        {
            await next.Invoke(environment);
        }
        finally
        {
            Interlocked.Decrement(ref requestCount);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是在管道中注册为第一个中间件,在程序的主要方法中我可以像这样使用它:

public class Program
{
    public static ManualResetEventSlim StopSwitch = new ManualResetEventSlim();

    static void Main(string[] args)
    {
        Console.CancelKeyPress += (s, a) =>
        {
            a.Cancel = true;
            StopSwitch.Set();
        };

        using (WebApp.Start<Startup>("http://+:8080/"))
        {
            Console.WriteLine("Server is running...");
            Console.WriteLine("Press CTRL+C to stop it.");
            StopSwitch.Wait();
            Console.WriteLine("Server is stopping...");
            ShutDownMiddleware.ShutDown();
            while (ShutDownMiddleware.GetRequestCount() != 0)
            {
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我还发现了这个: https: //katanaproject.codeplex.com/workitem/281 他们正在谈论类似的方法。