TcpClient и NetworkStream решают проблему - PullRequest
1 голос
/ 20 июля 2009

Я использую этот кусок кода для обработки соединения с сервером и чтения данных с клиента

using(var client = _listener.EndAcceptTcpClient(ar))
{
        var clientStream = client.GetStream();
        // Get the request message 
        Messages.ReceiveMessage(clientStream, msg => ProcessRequest(msg, clientStream));
}

Теперь метод ReceiveMessage вызывает BeginRead() для потока, переданного в качестве параметра, но я получаю исключение ObjectDisposedException.

Я знаю, что решение заключается в вызове stream.Dispose (), когда мне больше не нужен Stream, но я действительно ищу решение, в котором я могу поддерживать использование предложения using.

Спасибо

Ответы [ 2 ]

3 голосов
/ 20 июля 2009

Здесь есть две возможности.

Во-первых, вы можете взять этот асинхронный процесс и заблокировать его до завершения, что позволит вам сохранить оператор using. Это подход , предложенный Беном М здесь .

В качестве альтернативы, вы можете удалить оператор using и удалить клиентскую переменную самостоятельно. Это может показаться более громоздким, чем использование синтаксиса компилятора для использования, но оно дает преимущество, позволяя вам поддерживать асинхронное поведение, которым вы в настоящее время пытаетесь воспользоваться в этой ситуации, и устраняет необходимость в блоках. Однако это потребует от вас сохранения переменной и ее утилизации в соответствующем месте (возможно, в конце вашего делегата, но для этого также, вероятно, потребуется проверить ее позже, на тот случай, если делегат никогда не вызывается).

Оператор "using" в C # хорош, но есть ситуации, когда он не подходит, и это может быть одним из них (если вам нужно сохранить асинхронное поведение).

2 голосов
/ 20 июля 2009

Вы можете сделать это:

using (var client = _listener.EndAcceptTcpClient(ar))
{
    var clientStream = client.GetStream();

    using (var eh = new ManualResetEvent(false))
    {
        // Get the request message 
        Messages.ReceiveMessage(clientStream, msg =>
            {
                ProcessRequest(msg, clientStream);
                eh.Set();
            });

        eh.WaitOne();
    }
}

Одно предостережение: если есть где-нибудь разумное (экземпляр класса) для хранения ManualResetEvent, чтобы его можно было использовать повторно, сделайте это - поскольку создание / уничтожение множества из них может быть немного непонятным.

Также обратите внимание, что из поведения, описанного вами в посте, я предполагаю, что ReceiveMessage () является асинхронной операцией.

...