如何正确处理asyc NetworkStream

时间:2015-12-02 09:26:23

标签: c# tcp networkstream objectdisposedexception

我试图在完成写作后处理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 个答案:

答案 0 :(得分:3)

由于对stream.BeginWrite(...)的调用是非阻塞的,因此在写操作完成之前将使用using块,因此异常。处理流的适当位置将在回调函数中。

答案 1 :(得分:1)

Stefans的回答是正确的,并指出了根本原因。你应该接受它。我将添加另一种解决问题的方法:

此代码已过时,请使用等待。接下来,您将创建无限量的并发发送。这很容易耗尽资源。它甚至可能导致腐败,不确定。

按顺序执行发送。这是非常容易和自然的等待。

if (stream.CanWrite)

这没有想到... CanWrite将始终返回true,如果返回false,您将无所事事并隐藏错误。