【问题标题】:HttpListener Async Context leakingHttpListener 异步上下文泄漏
【发布时间】:2016-01-05 20:03:25
【问题描述】:

我有一个简单的 HTTPServer 实现,它使用 System.Net.HttpListener。似乎我的 AsyncCallbacks 没有以某种方式处理,因此导致泄漏。

public abstract class HttpServer : IHttpServer, IDisposable
{
    protected readonly HttpListener HttpListener = new HttpListener();

    protected HttpServer(IEnumerable<string> prefixes)
    {
        WaitOnStartup = new AutoResetEvent(false);
        foreach (var prefix in prefixes)
        {
            HttpListener.Prefixes.Add(prefix);
        }
    }

    private void Process()
    {
        var result = HttpListener.BeginGetContext(ContextReceived, HttpListener);
        result.AsyncWaitHandle.WaitOne(30000);
        result.AsyncWaitHandle.Dispose();
    }

    protected abstract void ContextReceived(IAsyncResult ar);

    [...]
}

public class MyHttpServer : HttpServer
{
    public MyHttpServer(IEnumerable<string> prefixes) : base(prefixes) { }

    protected override void ContextReceived(IAsyncResult ar)
    {
        var listener = ar.AsyncState as HttpListener;
        if (listener == null) return;
        var context = listener.EndGetContext(ar);
        try
        {
            var request = context.Request;
            var response = context.Response;

            //handle the request...
        }
        finally
        {
            context.Response.Close();
            listener.Close();
        }
    }
}

如果我运行内存分析器,它看起来异步句柄 (BeginGetContext) 没有被释放,这意味着 AsyncCallback 对象不断增加......

我错过了什么??

更新 11:45:

这里是基类(HttpServer)的Dipose()

protected virtual void Dispose(bool disposing)
{
    if (_disposed)
        return;

    if (disposing)
    {
        // Free any other managed objects here. 
        HttpListener.Stop();
        HttpListener.Close();
        WaitOnStartup.Dispose();
    }

    // Free any unmanaged objects here. 
    //
    _disposed = true;
}

【问题讨论】:

  • 你是如何实现 Dispose 方法的?
  • 是的,我在基类中有一个 Dispose()。更新示例以显示该片段。

标签: c# memory-leaks


【解决方案1】:

看起来我设法找到了问题,但我还不确定为什么......

但在@csharptest.net 在Multi-threading with .Net HttpListener 中发布的答案的启发下,我替换了使用:

private void Process()
{
    var result = HttpListener.BeginGetContext(ContextReceived, HttpListener);
    result.AsyncWaitHandle.WaitOne(30000);
    result.AsyncWaitHandle.Dispose();
}

private void Process()
{
    while (HttpListener.IsListening)
    {
        var result = HttpListener.BeginGetContext(ContextReceived,     HttpListener);
        if (WaitHandle.WaitAny(new[] { result.AsyncWaitHandle, _shutdown })     == 0)
            return;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多