Как я могу реализовать asyn c, основанный на TcpClient / NetworkStream порт этого блокирующего метода Socket? - PullRequest
0 голосов
/ 23 марта 2020

У меня есть такой код:

  public byte[] Read()
  {
     try
     {
        if (ClientSocket.Available != 0)
        {
           var InBuffer = new byte[ClientSocket.Available];
           ClientSocket.Receive(InBuffer);
           return InBuffer;
        }
        else
        {
           return null;
        }

     }
     catch (Exception ex)
     {
        Console.WriteLine(ex.ToString());
     }

  }

Я хотел бы сделать async эквивалент без полного изменения потока кода (бородавки и все), и я сталкиваюсь с проблемами, я также хочу переключиться на NetworkStream, поскольку он имеет встроенные async методы

Я бы хотел, чтобы sig был Task<byte[]> Read(), но:

  1. NetworkStream.ReadAsync ожидает передается byte[], но не возвращает его, поэтому я просто не могу return stream.Read(...)
  2. NetworkStream не сказать, сколько байтов доступно для чтения.
  3. Если нет доступных данных, я не хочу звонить stream.Read, просто передать ноль.

Так что независимо от проблем в вышеупомянутом методе - я знаю, что это не оптимально - как Могу ли я сделать это?

Цель, которую я могу сделать, или эквивалент.

byte [] bytes = await x.Read();

1 Ответ

1 голос
/ 23 марта 2020

NetworkStream.ReadAsyn c похоже на большинство методов «дай мне буфер байтов», с которыми я сталкивался; Вы даете ему байтовый массив и просите его прочитать количество байтов из сети X и поместить его в буфер. Он может читать меньше, чем вы просили, но больше не будет читать. Возвращает количество прочитанных байтов. Ваш код всегда держится в буфере байтового массива, поэтому вы должны выполнить что-то вроде этого:

byte[] buf = new byte[4096];
int bytesRead = await networkStream.ReadAsync(buf, 0, buf.Length. someCancelationToken);

byte[] rtn = new byte[bytesRead];
Array.Copy(buf, 0, rtn, 0, rtn.Length);

return rtn;

То есть вы читаете как Asyn c op, а затем возвращаете размер массива точное количество байтов, сообщаемых как прочитанные, которые поступают из буфера. Метод, использующий этот код, будет возвращать задачу

. NetworkStream также имеет метод CanRead, который должен соответствовать вашему требованию «если нечего читать»

Существует также перегрузка ReadAsyn c, который принимает от вас Память в качестве буфера. Вы бы использовали это аналогичным образом, за исключением того, что вызывали бы метод Slice, когда вы знали, сколько байтов было прочитано, чтобы вернуть вам память, смотрящую только на этот раздел буфера. Если бы вы вызвали ToArray в результате вызова Slice, вы бы получили массив по своему вкусу (считанные байты). Скорее всего, в этом контексте разница между ними невелика, хотя использование Memory (и связанного с ней класса Span) может уменьшить количество выделенных памяти для некоторых операций

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...