Закрытие NetworkStream после вызова BeginRead () в C # - PullRequest
5 голосов
/ 17 августа 2011

Я реализовал систему, которая имитирует событие DataReceived последовательного порта, в результате чего чтение данных из объекта NetworkStream объекта TCPClient запускается с помощью метода BeginRead () следующим образом:

TcpClient server = new TcpClient();
server.Connect(IPAddress.Parse(ip), 10001);
server.GetStream().BeginRead(buffer, 0, buffer.Length, new AsyncCallback(DataReceived), server.GetStream());

, которыйвызывает следующий метод из другого потока:

 private void DataReceived(IAsyncResult result)
    {
        res = result;
        server.GetStream().EndRead(result);

        //append received data to the string buffer
        stringBuffer += System.Text.ASCIIEncoding.ASCII.GetString(buffer);

        //clear the byte array
        Array.Clear(buffer, 0, buffer.Length);

        //trigger the parser
        waitHandle.Set();

        server.GetStream().BeginRead(buffer, 0, buffer.Length, new AsyncCallback(DataReceived), buffer);
    }

Кажется, это работает правильно.Я могу отправлять и получать данные на устройство в сети без проблем.Тем не менее, когда я пытаюсь отключиться, используя следующий метод, программа падает:

public override void disconnect()
{
    server.Close();
}

Выдает следующую ошибку:

A first chance exception of type 'System.ObjectDisposedException' occurred in System.dll

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

server.GetStream().Close();

но это приводит к следующей ошибке:

A first chance exception of type 'System.InvalidOperationException' occurred in System.dll

Я предполагаю, что это как-то связано с тем, что был вызван метод BeginRead () и EndRead () метод не имеет.Если это так, как я могу закрыть поток без сбоев?

1 Ответ

1 голос
/ 17 августа 2011

Я бы назвал GetStream только один раз и сохранил бы результат где-нибудь и использовал бы его для доступа к потоку.

Stream nstrm = server.GetStream();

Используйте nstrm для всех обращений к NetworkStream ...

самый безопасный способ - сохранить флаг для закрытия и просто установить этот флаг в disconnect().

В DataReceived вы бы сразу после EndRead проверили этот флаг и, если он установлен, сделайте следующее:

server.Close();
nstrm.Close();

см. http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.getstream.aspx

РЕДАКТИРОВАТЬ - согласно комментарию:

if (flag2Close)
{
    server.Close();
    nstrm.Close();
    flag2Close = false;
}
else
{
    nstrm.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(DataReceived), buffer);
}

Кстати: для производственного кода требуется некоторая обработка исключений и т. Д.

...