Как правильно утилизировать asyc NetworkStream
Я пытаюсь избавиться от NetworkStream
после того, как он закончил писать. Я пытался обернуть поток в using()
вот так:
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);
}
}
}
}
}
2 ответа
Поскольку вызов stream.BeginWrite(...) не является блокирующим, блок using будет оставлен до завершения операции записи, отсюда и исключение. Правильное место для удаления потока будет в функции обратного вызова.
Ответ Стефана правильный и указывает на основную причину. Вы должны принять это. Я добавлю еще один способ решения проблемы:
Этот код устарел, используйте await. Затем вы создаете неограниченное количество одновременных отправок. Это может легко истощить ресурсы. Это может даже привести к коррупции, не уверен.
Выполните посылку последовательно. Это очень легко и естественно с ожиданием.
if (stream.CanWrite)
Это не продумано... CanWrite всегда будет возвращать true, а если он возвращает false, вы просто ничего не делаете и скрываете ошибку.