Reputation: 79
I am creating a windows service that listens for specific Http requests. I am running an httpListener
in a separate task. When the service is stopped i close the listener instance. But it seems that the http listenerContext is waiting for an incoming request and as the listener get closed i get the following error
Cannot access a disposed object. Object name: 'System.Net.HttpListener'.
Even if i use some mechanism to inform StartListening()
that listening is stopped, it will not run as the execution at the corresponding thread stuck at HttpListenerContext context = await _listener.GetContextAsync();
until a request arrives.
public void StartListening() {
_listener.Start();
_logger.LogDebug("Http Listening started");
Task.Run(async () => {
while (true) {
try {
if (isOpen == false) {
return 0;
}
HttpListenerContext context = await _listener.GetContextAsync();
HttpListenerRequest request = context.Request;
//processing of the requests url/////
var newUri = request.Url.AbsoluteUri;
_concurrentUrlQueue.Enqueue(newUri);
if (ConcurentUrlQueueChanged != null) ConcurentUrlQueueChanged(this, new EventArgs());
}
catch (Exception e) {
_logger.LogError("Error at get listening context, Message: " + e.Message);
}
}
});
}
public void StopListening() {
isOpen = false;
_logger.LogDebug("Http Listening Stop");
_listener.Close();
}
Which is the appropriate way to close an http listener that is listening to get context. The code i use is the following. Thank you..
Upvotes: 2
Views: 8507
Reputation: 79
I found a solution. As i understand the listener.GetContextAsync()
is a blocking method, and the execution of my code will only continiou when a new context is detected. I can use the non blocking versions BeginGetContext() and EndGetContext(). When i want to stop execution i use a cancellation token.
public void StartListening() {
_listener.Start();
_logger.LogDebug("Http Listening started");
Task.Run(() => {
while(true) {
if(_cancellationToken.IsCancellationRequested) return ;
try {
NonblockingListener();
}
catch (Exception e) {
_logger.LogError("Error With the listening Proccess, Message : "+e.Message);
}
}
},_cancellationToken);
}
public void StopListening() {
_cancellationTokenSource.Cancel();
ListenerCallback(null);
_logger.LogDebug("Http Listening Stop");
_listener.Close();
}
public void NonblockingListener() {
IAsyncResult result = _listener.BeginGetContext(ListenerCallback, _listener);
result.AsyncWaitHandle.WaitOne();
}
public void ListenerCallback(IAsyncResult result) {
if(_cancellationToken.IsCancellationRequested)return;
_listener = (HttpListener)result.AsyncState;
HttpListenerContext context = _listener.EndGetContext(result);
HttpListenerRequest request = context.Request;
//processing code
EnqueUrl(request);
}
Upvotes: 2