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); 
} 

以下のように設定されているアクションがあり

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"); 
     } 
    } 
} 

次のようにHTTP GETリクエストを受け付けたURL http://127.0.0.1:54781/を開いて、私は進歩的な応答来を参照してください。

しかし、サーバーが応答を送信しているときにクライアントが接続を終了すると、完了ポートのスレッドは占有され、決して解放されません。 enter image description here

それ完了ポートスレッドプールを排出することによって、アプリケーションをダウンさせることができます。

答えて

0

OWINセルフホスティングに変更すると、この問題は解決します。この投稿に来て他の人のために

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); 
    } 
} 
0

デフォルトでCPUコアを使用していますSystem.Web.Http.SelfHostで同様の問題がある*と同じである100件のスレッド:ここでSystem.Web.Http.SelfHost

のバグがコードに更新されているようですMonoはすべてのスレッドを事前に作成するため、デフォルトのThreadPoolの制限はデッドロックで終了します。

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

関連する問題