首页 文章

停止并重新启动HttpListener?

提问于
浏览
1

我正在开发一个有 HttpListener 的应用 . 我的目标是让用户在他们选择时关闭和打开监听器 . 我把Listener放在一个新线程中,我遇到了一个问题,就是在中止该线程 . 我读到某个地方,如果你试图中止一个处于非托管上下文中的线程,那么只要它重新进入托管上下文,就会触发 ThreadAbortException . 似乎HttpListener的 GetContext() 方法是不受管理的,因为当我尝试中止线程时,在我针对我的应用程序发出Web请求之前没有任何事情发生 . 然后线程退出 . 问题是当我试图杀死线程时,我可能稍后在同一端口再次启动线程,并且 HttpListenerException 说明前缀已经注册 .

我怎么能杀死一个交叉线程HttpListener?是否有一个托管替代 GetContext() 将允许线程中止?我可以以非托管代码停止的方式中止线程吗?

3 回答

  • 0

    你需要通知线程调用HttpListener.Stop()并通过调用Thread.Join()等待线程完成

  • 1

    怎么样的:

    public class XListener
    {
        HttpListener listener;
    
        public XListener(string prefix)
        {
            listener = new HttpListener();
            listener.Prefixes.Add(prefix);
        }
    
        public void StartListen()
        {
            if (!listener.IsListening)
            {
                listener.Start();
    
                Task.Factory.StartNew(async () =>
                {
                    while (true) await Listen(listener);
                }, TaskCreationOptions.LongRunning);
    
                Console.WriteLine("Listener started");
            }
        }
    
        public void StopListen()
        {
            if (listener.IsListening)
            {
                listener.Stop();
                Console.WriteLine("Listener stopped");
            }
        }
    
        private async Task Listen(HttpListener l)
        {
            try
            {
                var ctx = await l.GetContextAsync();
    
                var text = "Hello World";
                var buffer = Encoding.UTF8.GetBytes(text);
    
                using (var response = ctx.Response)
                {
                    ctx.Response.ContentLength64 = buffer.Length;
                    ctx.Response.OutputStream.Write(buffer, 0, buffer.Length);
                }
            }
            catch (HttpListenerException)
            {
                Console.WriteLine("screw you guys, I'm going home!");
            }
        }
    }
    

    用法:

    var x = new XListener("http://locahost:8080");
    
    x.StartListen();
    Thread.Sleep(500); // test purpose only
    
    x.StopListen();
    Thread.Sleep(500); // test purpose only
    
    x.StartListen();
    
    /* OUTPUT:
    => Listener started
    => Listener stopped
    => screw you guys, I'm going home!
    => Listener started */
    
  • 3

    您需要做的就是在监听器上调用stop . 由于您的侦听器线程在 GetContext 上被阻止,因此您需要在另一个线程上执行此操作 . IIRC这将导致 GetContext 抛出,因此您将需要处理该异常并进行清理 . 调用 Thread.Abort 应该是你的最后手段,并且不会导致监听器停止监听,直到它被垃圾收集为止 .

相关问题