Как корректно остановить асинхронное чтение из UdpClient?
От: Аноним  
Дата: 23.07.08 08:31
Оценка:
Добрый день!

Пишу класс DataReceiver, получающий UDP пакеты и передающий их в очередь для дальнейшей обработки. Получение реализовано с использованием асинхронных методов BeginReceive, EndReceive класса UdpClient.

    public class DataReceiver : IDisposable
    {
        private UdpClient _client;
        private bool _disposed;

        public void Start()
        {
            _client.BeginReceive(ReceiveCallback, null);
        }

        public void Stop()
        {
            _client.Close();
        }

        private void ReceiveCallback(IAsyncResult ar)
        {
            IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);

            try
            {
                byte[] data = _client.EndReceive(ar, ref remoteEP);

                // Передача на обработку подписчику ...

                _client.BeginReceive(ReceiveCallback, null);
            }
            catch (ObjectDisposedException)
            { /* Stopped? */ }
            catch (SocketException)
            { /* Stopped? */ }
        }

        /* IDisposable Members implementation */
    }


Корректна ли данная реализация? Как правильно остановить получение данных?

В приведенном коде меня смущает необходимость перехватывать ObjectDisposedException и SocketException внутри ReceiveCallback. Эти исключения возникают, если ReceiveCallback срабатывает в результате или после вызова _client.Close. Поэтому в принципе, видится нормальным их перехват: DataReceiver полагает, что остановлен и не делает новых запросов на получение пакетов. Однако SocketException может возникнуть и "штатно", DataReceiver в этом случае поведет себя неправильно: прекратит дальнейшее получение пакетов.

Фактически, здесь проблема использования ресурса из разных потоков. UdpClient используется из основного потока, вызывающего Start, Stop, и потоками из пула, в контексте которых срабатывает ReceiveCallback. Возможно, стоит ввести флаг "остановлен" и синхронизировать доступ к нему и UdpClient? А как быть с блокировкой, которая появится в реализации Dispose?

 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.