C # HTTP Listener ObjectDisposedException при асинхронном получении запросов - PullRequest
1 голос
/ 08 апреля 2019

Я новичок, поэтому, пожалуйста, потерпите меня.

Я пытался написать очень простой C # HTTP Listener, который может обрабатывать клиентские запросы асинхронно.

Для этого я использовал этот пример кода из официальных документов Microsoft:

https://docs.microsoft.com/de-de/dotnet/api/system.net.httplistener.begingetcontext?view=netframework-4.7.2

Несмотря на то, что я использую один и тот же код, я получаю исключение ObjectDisposed,Я могу исправить это только вручную, ожидая несколько миллисекунд в главном потоке, но это ужасное решение, которое я хочу исправить, поскольку оно, очевидно, сильно замедляет все.

Кажется, что основной поток просто не 't ждать и закрывать слушателя до окончания работы, в результате чего объект преждевременно удаляется.Я полагаю, поэтому ручное ожидание исправляет это.Но почему метод WaitOne () не ждет?

Чтобы уменьшить количество личных ошибок, я сделал свой код почти идентичным образцу, я только добавляю префиксы вручную.

Слушатель:

public static void NonblockingListener()
{
    HttpListener listener = new HttpListener();
    listener.Prefixes.Add("http://localhost:8080/test/");
    listener.Start();

    IAsyncResult result = listener.BeginGetContext(new AsyncCallback(ListenerCallback),listener);

    Console.WriteLine("Waiting for request to be processed asyncronously.");
    result.AsyncWaitHandle.WaitOne();
    Console.WriteLine("Request processed asyncronously.");

    // It will only work if I add this: System.Threading.Thread.Sleep(200);
    listener.Close();
}

Метод обратного вызова:

public static void ListenerCallback(IAsyncResult result)
{
    HttpListener listener = (HttpListener) result.AsyncState;  

    // It throws the exception at this line
    HttpListenerContext context = listener.EndGetContext(result);

    HttpListenerRequest request = context.Request;
    HttpListenerResponse response = context.Response;

    string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
    byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
    response.ContentLength64 = buffer.Length;
    System.IO.Stream output = response.OutputStream;
    output.Write(buffer,0,buffer.Length);
    output.Close();
}

Наконец, вот как я настроил свою основную функцию, это всего лишь простой бесконечный цикл:

static void Main(string[] args)
{
     while (true)
         NonblockingListener();
}

Ябыть глупым или правильно предположить, что с примером кода что-то не так?Это было бы странно, но я действительно не знаю, что я делаю неправильно.

Если бы кто-то мог скопировать тот же пример кода и попробовать запустить его, это было бы здорово.

Что бы я изменил, чтобы он работал как положено?

1 Ответ

0 голосов
/ 08 апреля 2019

Я понял это сам через несколько более болезненных часов, я все равно просто выложу здесь ответ на случай, если у кого-то возникнет такая же проблема. Проблема заключалась в том, что я продолжал закрывать и воссоздавать Слушатель, а не использовать его для следующего запроса. Это ошибка, которую я скопировал с примера кодовой страницы MSDN. Он закрывает прослушиватель сразу после получения запроса клиента, что приводит к ошибке, поскольку метод обратного вызова больше не может получить доступ к закрытому прослушивателю для обработки все еще выполняющегося запроса.

Решение состоит в том, чтобы удалить цикл в главной функции и вместо этого поместить бесконечный цикл:

IAsyncResult result = listener.BeginGetContext(newAsyncCallback(ListenerCallback),listener);
result.AsyncWaitHandle.WaitOne();

Это кажется очевидным, но я думаю, что я просто принял MSDN как должное, что, по-видимому, является ошибкой.

...