I have a listener:
listener = new HttpListener(); listener.Prefixes.Add(@"http://+:8077/"); listener.Start(); listenerThread = new Thread(HandleRequests); listenerThread.Start();
And I am handling requests:
private void HandleRequests() { while (listener.IsListening) { var context = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener); context.AsyncWaitHandle.WaitOne(); } } private void ListenerCallback(IAsyncResult ar) { var listener = ar.AsyncState as HttpListener; var context = listener.EndGetContext(ar); //do some stuff }
I would like to write void Stop()
in such a way, that:
ListenerCallback
).listener.Stop()
(listener.IsListening
became false).How could it be write?
EDIT: What do you think about this solution? Is it safe?
public void Stop() { lock (this) { isStopping = true; } resetEvent.WaitOne(); //initially set to true listener.Stop(); } private void ListenerCallback(IAsyncResult ar) { lock (this) { if (isStopping) return; resetEvent.Reset(); numberOfRequests++; } var listener = ar.AsyncState as HttpListener; var context = listener.EndGetContext(ar); //do some stuff lock (this) { if (--numberOfRequests == 0) resetEvent.Set(); } }
For completeness, here is what it would look like if you manage your own worker threads:
class HttpServer : IDisposable { private readonly HttpListener _listener; private readonly Thread _listenerThread; private readonly Thread[] _workers; private readonly ManualResetEvent _stop, _ready; private Queue<HttpListenerContext> _queue; public HttpServer(int maxThreads) { _workers = new Thread[maxThreads]; _queue = new Queue<HttpListenerContext>(); _stop = new ManualResetEvent(false); _ready = new ManualResetEvent(false); _listener = new HttpListener(); _listenerThread = new Thread(HandleRequests); } public void Start(int port) { _listener.Prefixes.Add(String.Format(@"http://+:{0}/", port)); _listener.Start(); _listenerThread.Start(); for (int i = 0; i < _workers.Length; i++) { _workers[i] = new Thread(Worker); _workers[i].Start(); } } public void Dispose() { Stop(); } public void Stop() { _stop.Set(); _listenerThread.Join(); foreach (Thread worker in _workers) worker.Join(); _listener.Stop(); } private void HandleRequests() { while (_listener.IsListening) { var context = _listener.BeginGetContext(ContextReady, null); if (0 == WaitHandle.WaitAny(new[] { _stop, context.AsyncWaitHandle })) return; } } private void ContextReady(IAsyncResult ar) { try { lock (_queue) { _queue.Enqueue(_listener.EndGetContext(ar)); _ready.Set(); } } catch { return; } } private void Worker() { WaitHandle[] wait = new[] { _ready, _stop }; while (0 == WaitHandle.WaitAny(wait)) { HttpListenerContext context; lock (_queue) { if (_queue.Count > 0) context = _queue.Dequeue(); else { _ready.Reset(); continue; } } try { ProcessRequest(context); } catch (Exception e) { Console.Error.WriteLine(e); } } } public event Action<HttpListenerContext> ProcessRequest; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With