ObjectDisposedException для AcceptTcpClientAsync () для нового экземпляра TcpListener - PullRequest
0 голосов
/ 10 декабря 2018

Я застрял на проблеме с классом TcpListener, после остановки сервера и попытки запустить его снова.В основном я пытаюсь использовать метод AcceptTcpClientAsync() для обработки входящих запросов на подключение и предоставления возможности перезапустить сервер.

Минимальный пример:

class Program
{
    private static TcpListener listener;

    static void Main(string[] args)
    {
        StartServerAsync();

        StopServer();

        StartServerAsync();

        Console.ReadKey();
    }

    private static void StopServer()
    {
        if (listener != null)
            listener.Stop();
    }

    private async static void StartServerAsync() 
    {
        listener = new TcpListener(IPAddress.Loopback, 1234);
        listener.Start();

        while (true)
        {
            var client = await listener.AcceptTcpClientAsync();
        }
    }
}

На второмЗвоните на await listener.AcceptTcpClientAsync() Я получаю ObjectDisposedException для сокета.

Любая идея или вход, как преодолеть эту проблему?

Спасибо!

1 Ответ

0 голосов
/ 10 декабря 2018

Кажется, нездоровая комбинация статических переменных и async void.После некоторой перезаписи, чтобы удалить статическую переменную и использовать фабричный метод, который возвращает слушателя, исключение все еще происходит.Но теперь я получил это в ожидании вызова соответствующего экземпляра, где был вызван Stop().Это имеет смысл, потому что вызов accept должен возвращаться после остановки, но он должен сигнализировать, что клиент недоступен (что он делает, выбрасывая исключение).

Итак избежать async voidособенно в сочетании со статическими элементами.Кажется, ядовито, и мне жаль, что у меня нет более глубокого объяснения (кроме ссылки).

private static void Main(string[] args)
{
    var listener1 = StartServerAsync(1234).Result;
    StopServer(listener1);
    var listener2 = StartServerAsync(1235).Result;
    StopServer(listener2);
    var listener3 = StartServerAsync(1236).Result;
    StopServer(listener3);

    Console.ReadKey();
}

private static void StopServer(TcpListener listener)
{
    if (listener != null)
    {
        Console.WriteLine("Stop on port "+ listener.LocalEndpoint);
        listener.Stop();
        listener = null;
    }
}

private static async Task<TcpListener> StartServerAsync(int port)
{
    var listener = new TcpListener(IPAddress.Loopback, port);
    listener.Start();
    Console.WriteLine("Started on port " + port);

    var task = Task.Run(async () => await WaitForConnection(listener));
    await Task.Delay(100);

    return listener;
}

private static async Task WaitForConnection(TcpListener listener)
{
    while (true)
    {
        try
        {
            var client = await listener.AcceptTcpClientAsync();
        }
        catch (ObjectDisposedException)
        {
            Console.WriteLine("Failed on " + listener.LocalEndpoint);
        }
    }
}
...