0

ASP.NET WebApi 自己ホスト型アプリケーションがあります。HttpSelfHostConfiguration以下のように構成されています

HttpSelfHostConfiguration config = new HttpSelfHostConfiguration("http://0.0.0.0:54781")
{
    TransferMode = TransferMode.StreamedResponse,
    MaxConcurrentRequests = 1000,
    SendTimeout = TimeSpan.FromMinutes(60),
};

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "{controller}",
    defaults: new { @controller = "Default" }
);

HttpSelfHostServer server = new HttpSelfHostServer(config);
server.OpenAsync().Wait();

for (;;)
{
    int workerThreads, completionPortThreads;
    ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
    Console.WriteLine("Available Completion Port Threads = {0};", completionPortThreads);
    Console.Out.Flush();
    Thread.Sleep(2000);
}

以下のようにHTTP GETリクエストを受け入れるアクションがあります

public class DefaultController : ApiController
{
    public HttpResponseMessage GET()
    {
        Console.WriteLine("Receive HTTP GET request");
        Func<Stream, HttpContent, TransportContext, Task> func = (stream, httpContent, transportContext) =>
        {
            return Monitor(httpContent, stream);
        };


        HttpResponseMessage response = Request.CreateResponse();

        response.StatusCode = HttpStatusCode.OK;
        response.Content = new PushStreamContent(func, new MediaTypeHeaderValue("text/plain"));
        return response;
    }

    async Task Monitor(HttpContent httpContent, Stream stream)
    {
        try
        {
            using (StreamWriter sw = new StreamWriter(stream, new UTF8Encoding(false)))
            {
                for (;;)
                {
                    sw.WriteLine(Guid.NewGuid().ToString());
                    sw.Flush();

                    await Task.Delay(1000);
                }
            }
        }
        catch (CommunicationException ce)
        {
            HttpListenerException ex = ce.InnerException as HttpListenerException;
            if (ex != null)
            {
                Console.WriteLine("HttpListenerException occurs, error code = {0}", ex.ErrorCode);
            }
            else
            {
                Console.WriteLine("{0} occurs : {1}", ce.GetType().Name, ce.Message);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("{0} occurs : {1}", ex.GetType().Name, ex.Message);
        }
        finally
        {
            stream.Close();
            stream.Dispose();
            httpContent.Dispose();
            Console.WriteLine("Dispose");
        }
    }
}

URL を開くと、http://127.0.0.1:54781/プログレッシブ応答が表示されます。

ただし、サーバーが応答を送信しているときにクライアントが接続を終了すると、完了ポート スレッドが使用され、解放されません。

ここに画像の説明を入力

完了ポートのスレッド プールを使い果たすことで、アプリケーションをダウンさせることができます。

4

2 に答える 2

0

OWIN セルフホスティングに変更すると、この問題はなくなります。バグのようですSystem.Web.Http.SelfHost

更新されたコードは次のとおりです。

class Program
{

    static void Main(string[] args)
    {
        var server = WebApp.Start<Startup>(url: "http://*:54781");


        for (;;)
        {
            int workerThreads, completionPortThreads;
            ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
            Console.WriteLine("Worker Threads = {0}; Available Completion Port Threads = {1};", workerThreads, completionPortThreads);
            Console.Out.Flush();
            Thread.Sleep(2000);
        }
    }
}

public class Startup
{
    // This code configures Web API. The Startup class is specified as a type
    // parameter in the WebApp.Start method.
    public void Configuration(IAppBuilder appBuilder)
    {
        // Configure Web API for self-host. 
        HttpConfiguration config = new HttpConfiguration();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "{controller}",
            defaults: new { @controller = "Default" }
        );

        appBuilder.UseWebApi(config);
    }
}
于 2016-05-05T05:13:14.653 に答える
0

この投稿に来る他の人には、System.Web.Http.SelfHostデフォルトで CPU コア * 100 スレッドを使用するという同様の問題があります。これは、Mono がすべてのスレッドを事前に作成するため、デッドロックで終了するデフォルトの ThreadPool 制限と同じです。

これを回避する最も簡単な方法は、MONO_THREADS_PER_CPU環境変数を 1 より大きい値に設定するか--server、Mono アプリケーションの実行時にフラグを使用することです。

于 2017-01-26T14:14:33.087 に答える