c# - 从 NetworkStream 读取 BinaryFormatter 序列化对象的最有效方法?

标签 c# .net-4.5 async-await networkstream c#-5.0

我有一个应用程序通过套接字连接发送不同大小的可序列化对象,我希望它尽可能具有可扩展性。也可能有数十个甚至数百个连接。

  1. NetworkStream 来自持续监听传入消息的 TcpClient。
  2. 我不想用标准 NetworkStream.Read() 阻塞线程。这需要扩展。我只是假设 Read() block ,因为对于这类类来说这是非常标准的行为,并且类上有一个 ReadTimeout 属性。
  3. 我不确定 BinaryFormatter 是只使用 Read() 还是它在后台为我做了一些异步操作。我猜不会。
  4. TcpClient 需要获取一条消息,读到最后,然后返回监听消息。

所以似乎有太多方法可以给这只猫剥皮,我不确定哪种方法最有效。我是否:

简单地使用 BinaryFormatter 来读取 NetworkStream?

var netStream = client.GetStream();
var formatter = new BinaryFormatter();
var obj = formatter.Deserialize(netStream);

使用新的异步/等待功能施展魔法:

using(var ms = new MemoryStream()) 
{
   var netStream = client.GetStream();
   var buffer = new byte[1028];
   int bytesRead;
   while((bytesRead = await netStream.ReadAsync(buffer, 0, buffer.length)) > 0) {
      ms.Write(buffer, 0, buffer.Length);
   }
   var formatter = new BinaryFormatter();
   var obj = formatter.Deserialize(ms);
}

OR 与上述类似,仅利用新的 CopyToAsync 方法:

using(var ms = new MemoryStream()) 
{
   var netStream = client.GetStream();
   await netStream.CopyToAsync(ms); //4096 default buffer.
   var formatter = new BinaryFormatter();
   var obj = formatter.Deserialize(ms);
}

或者还有什么?

我正在寻找可提供最大可扩展性/效率的答案。

[注:以上均为伪代码,仅作为示例]

最佳答案

第一种方法在大数据流方面存在问题。如果您要发送大数据,该代码将导致应用程序出现内存不足异常。

第二种方法看起来非常好 - 它是异步的(意味着您不使用一些有值(value)的线程来等待读取完成)并且它使用数据 block (这就是您应该如何处理流)。

因此选择第二个选项,可能稍作修改 - 一次只反序列化数据 block ,不要读取整个数据(除非您完全确定流长度)。

这就是我的想法(伪代码)

using (var networkStream = client.GetStream()) //get access to stream
{
    while(!networkStream.EndOfStream) //still has some data
    {
        var buffer = new byte[1234]; //get a buffer
        await SourceStream.ReadAsync(result, 0, buffer); //read from network there

        //om nom nom buffer     
        Foo obj;
        using(var ms = new MemoryStream()) //process just one chunk
        {
             ms.Write(buffer, 0, buffer.Length);
             var formatter = new BinaryFormatter();
             obj = formatter.Deserialize(ms);   //desserialise the object        
        } // dispose memory

        //async send obj up for further processing
    }
}

关于c# - 从 NetworkStream 读取 BinaryFormatter 序列化对象的最有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14223379/

相关文章:

c# - 使 IIS 7.5 将 *.xml 请求传递给 asp.net

c# - Enumerable.Repeat 有一些内存问题?

C# HttpClient 4.5 多部分/表单数据上传

c# - 处理来自线程的值 执行yield return函数

c# - 如果行已存在,如何将行插入表或添加值

c# - 如何修复 Microsoft Visual Studio 错误 : "package did not load correctly"?

asp.net - 是否可以在 Web API 中使用 ASP.NET 应用程序缓存?

c# - 在 C# 中生成位图 - 已弃用?

javascript - 将 knex 递减与异步/等待一起使用

C# 在同步上下文中运行异步任务