У меня проблема. В приведенном ниже коде используется шаблон async/await с HttpListener. Когда запрос отправляется через HTTP «delay», запрашивается строковый аргумент запроса, и его значение заставляет сервер задерживать указанную обработку запроса за данный период. Мне нужен сервер для обработки ожидающих запросов даже после того, как сервер перестает получать новые запросы.Как предотвратить HttpListener от прерывания ожидающих запросов при остановке? HttpListener.Stop не работает
static void Main(string[] args)
{
HttpListener httpListener = new HttpListener();
CountdownEvent sessions = new CountdownEvent(1);
bool stopRequested = false;
httpListener.Prefixes.Add("http://+:9000/GetData/");
httpListener.Start();
Task listenerTask = Task.Run(async() =>
{
while (true)
{
try
{
var context = await httpListener.GetContextAsync();
sessions.AddCount();
Task childTask = Task.Run(async() =>
{
try
{
Console.WriteLine($"Request accepted: {context.Request.RawUrl}");
int delay = int.Parse(context.Request.QueryString["delay"]);
await Task.Delay(delay);
using (StreamWriter sw = new StreamWriter(context.Response.OutputStream, Encoding.Default, 4096, true))
{
await sw.WriteAsync("<html><body><h1>Hello world</h1></body></html>");
}
context.Response.Close();
}
finally
{
sessions.Signal();
}
});
}
catch (HttpListenerException ex)
{
if (stopRequested && ex.ErrorCode == 995)
{
break;
}
throw;
}
}
});
Console.WriteLine("Server is running. ENTER to stop...");
Console.ReadLine();
sessions.Signal();
stopRequested = true;
httpListener.Stop();
Console.WriteLine("Stopped accepting requests. Waiting for the pendings...");
listenerTask.Wait();
sessions.Wait();
Console.WriteLine("Finished");
Console.ReadLine();
httpListener.Close();
}
Точная проблема здесь в том, что когда сервер остановлен HttpListener.Stop называется, но все ожидающие запросы прерываются немедленно, то есть код не может отправить ответы обратно.
В шаблоне non-async/await (т.е. простая реализация на основе Thread) У меня есть выбор, чтобы прервать поток (который, я полагаю, очень плохой), и это позволит мне обрабатывать ожидающие запросы, потому что это просто отменяет HttpListener. Вызов GetContext.
Не могли бы вы указать мне, что я делаю неправильно и как я могу предотвратить HttpListener для отмены ожидающих запросов в шаблоне async/await?
Что я имел в виду, так это то, что мой сервер перестанет получать новые запросы и сможет обрабатывать ожидающие запросы. Но вызов HttpListener.Stop не позволяет мне отвечать на ожидающие запросы. Что касается CancellationToken в сценарии async/await, как это может мне помочь, если HttpListener.GetContextAsync вообще не принимает CancellationToken? – Rauf
@ Luaan, кстати, спасибо, я обновил текст и заголовок вопроса. – Rauf
@ Luaan, кажется, ошибка. Не удалось заставить HttpListener приостановить прием запросов и обработать ожидающие. Даже попробовал пару Begin/EndGetContext. Еще не повезло. Фактически метод Thread.Abort помогает, поскольку он способен прервать вызов HttpListener.GetContext, не останавливая логику обработки запроса. – Rauf