0

Ich habe eine ASP.NET WebApi selbst gehostete Anwendung. HttpSelfHostConfiguration wie untenAbschluss Port Thread ist undicht, wenn Client die Verbindung beendet

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

konfiguriert Es ist eine Aktion akzeptiert HTTP-GET-Anfrage, wie unten

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

Öffnen der URL http://127.0.0.1:54781/ und ich sehe progressive Antwort comming.

Aber wenn der Client die Verbindung beendet, wenn der Server die Antwort sendet, wird der Abschluss-Port-Thread aufgenommen und nie freigegeben.

enter image description here

Es kann die Anwendung bringen, indem die Fäden Pool Completion-Port anstrengend.

Antwort

0

Nach dem Wechsel zu OWIN-Self-Hosting verschwindet dieses Problem. Es scheint ein Fehler in System.Web.Http.SelfHost

Hier Code aktualisiert:

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

Für andere zu diesem Beitrag kommen gibt es ein ähnliches Problem in System.Web.Http.SelfHost die standardmäßig CPU Cores * 100 Threads verwendet, die die gleiche wie die ist Das Standard-ThreadPool-Limit endet in einem Deadlock, da Mono alle Threads vorab erstellt.

Der einfachste Weg, dies zu umgehen, ist, die Umgebungsvariable MONO_THREADS_PER_CPU auf einen Wert größer als 1 zu setzen oder das Flag --server beim Ausführen der Mono-Anwendung zu verwenden.