2015-12-02 3 views
2

Я пытаюсь избавиться от NetworkStream после его написания. Я попытался обертывание потока в using() так:Как правильно утилизировать asyc NetworkStream

using (NetworkStream stream = client.GetStream()) 
{ 
    foreach (byte[] command in fadeSceneOut) 
    { 
      if (stream.CanWrite) 
      { 
       stream.BeginWrite(command, 0, command.Length, new AsyncCallback(SendCallback), stream); 
      } 
    } 
} 

Но я получаю System.ObjectDisposedException о том, что объект уже выброшен и не может быть доступен в моем обратном вызове, где я посылаю EndWrite():

private static void SendCallback(IAsyncResult ar) 
{ 
    try 
    { 
     NetworkStream stream = (NetworkStream)ar.AsyncState; 
     stream.EndWrite(ar); 
    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.ToString()); 
    } 
} 

Мое понимание заключалось в том, что поток не будет удален до тех пор, пока выполнение не покинет блок using после того, как все команды будут записаны в поток. Очевидно, я здесь что-то не так, может кто-нибудь посоветовать правильный подход?

Редактировать: включали await подход:

static void Main(string[] args) 
{ 
    Task.WaitAll(Run()); 
} 

public static async Task Run() 
{ 
    // Get a scene 
    var scene = GrabSceneFromUser(); 

    // Get scene commands 
    var fadeSceneIn = LightSwarmHelper.BuildSceneCommands(scene); 
    var fadeSceneOut = LightSwarmHelper.BuildSceneCommands(scene, false); 

    // Send commands to device 
    using (TcpClient client = new TcpClient(ConfigurationManager.AppSettings["Host"], Convert.ToInt32(ConfigurationManager.AppSettings["Port"]))) 
    { 
     using (NetworkStream stream = client.GetStream()) 
     { 
      foreach (byte[] command in fadeSceneOut) 
      { 
       if (stream.CanWrite) 
       { 
        await stream.WriteAsync(command, 0, command.Length); //stream.BeginWrite(command, 0, command.Length, new AsyncCallback(SendCallback), stream); 
       } 
      } 
     } 
    } 
} 
+0

Этот код устарел, используйте ожидание. Затем вы создаете неограниченное количество одновременных отправлений. Это может легко исчерпать ресурсы. Выполняйте отправку последовательно. Это может даже привести к коррупции, не уверен. – usr

+0

@usr Не знаком с 'await'. Невозможно найти примеры с помощью «NetworkStream», можете ли вы уточнить? – DGibbs

+0

Google для «.net NetworkStream ждут». – usr

ответ

3

Поскольку вызов stream.BeginWrite (...) не является блокирование, то с помощью блока-будет оставлен до завершения операции записи, следовательно, исключение. Правильное место для утилизации потока будет в функции обратного вызова.

+0

Это была моя первая догадка, но я все равно получаю ту же ошибку, по-видимому, потому, что я запускаю разные потоки для каждой команды, тогда она удалит поток до того, как все потоки закончат выполнение – DGibbs

+0

. Вам нужно будет отслеживать, как многие операции записи завершились, а затем удалили поток только в том случае, если это был обратный вызов для последней записи. – Stefan

1

Ответ Stefans правильный и указывает на основную причину. Вы должны это принять. Я добавлю еще один способ решить проблему:

Этот код устарел, используйте его. Затем вы создаете неограниченное количество одновременных отправлений. Это может легко исчерпать ресурсы. Это может даже привести к коррупции, не уверен.

Выполняйте отправку последовательно. Это очень легко и естественно с нетерпением.

if (stream.CanWrite) 

Это не продумана ... CanWrite всегда возвращает истину, и если он возвращается ложь просто не будет делать ничего, и скрыть ошибку.

+0

Я собираюсь обновить свой вопрос с помощью некоторого примера кода, используя 'await'. Это работает, но мне кажется, что это неправильно. Не могли бы вы взглянуть? – DGibbs

+0

Выглядит правильно. Какие-то конкретные заботы? Удалите предмет буфера отправки. – usr

+0

Запуск этого консольного приложения на данный момент, похоже, что он не дожидается, пока все тексты не будут записаны в поток, поскольку я иногда вижу только одну команду, отправленную, а иногда и вовсе. Если я добавлю 'Console.Read();' он отправит их все. Моя цель - заставить его подождать, пока все не будет записано, а затем удалите поток. – DGibbs

Смежные вопросы