【问题标题】:NetworkStream a thing i don´t understand in my codeNetworkStream 一个我在我的代码中不理解的东西
【发布时间】:2013-08-06 04:04:11
【问题描述】:

我在上一个关于如何发送图片的问题中获得了帮助。 所做的事情是先发送图像的长度(大小),然后发送实际图像,然后它会知道何时完成。

它看起来像这样:

BinaryWriter writer = new BinaryWriter(netStream);
while (someCondition) {
  Image img = SomeImage();
  MemoryStream ms = new MemoryStream();
  img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
  byte[] buffer = new byte[ms.Length];
  ms.Seek(0, SeekOrigin.Begin);
  ms.Read(buffer, 0, buffer.Length);
  writer.Write(buffer.Length);
  writer.Write(buffer);

此代码来自:Angelo Geels,他在上一个问题中帮助了我。

现在,我尝试以某种方式对此进行优化。而且,它有效。但仅当文件为 bmp(未压缩)时,我不知道为什么。

                    using (MemoryStream ms = PrintWindow(process))
                    {
                        writer.Write((int)ms.Length);
                        writer.Write(ms.GetBuffer());
                    }

所以 PrintWindow 将图像保存到内存流并返回。所以 ms = memorystream 里面有我的图片。

所以对我来说,这应该可以完美地工作,因为我可以做同样的事情。

我发送文件的大小(内存流的长度)。 然后我在内存流中发送 byte[] 数据。

所以,它是一回事。

但是,它只适用于 bmp。

我唯一能想到的是,当我以压缩格式保存时,先写入 bmp 然后再编码,这会弄乱 getbuffer() 或其他东西。

但我仍然认为它应该有效。

【问题讨论】:

  • 该代码块中缺少 usings 让我深感担忧。

标签: c# optimization networkstream binaryreader


【解决方案1】:

你写了太多字节,使用 Write() 重载,让你指定要写多少:

    using (MemoryStream ms = PrintWindow(process)) {
        writer.Write((int)ms.Length);
        writer.Write(ms.GetBuffer(), 0, (int)ms.Length);
    }

【讨论】:

  • 很好,它可以工作,这就是为什么我不必从它的外观转换为字节数组的原因。谢谢:)
  • 顺便说一句,没有办法进一步优化它吗?我的意思是,我必须在文件之前写下文件的长度,所以它知道在哪里结束。有没有可能以某种方式改善这一点?
  • @user2587718 您从未转换为字节数组。相反,您从 ms 中读取块,将其写入临时缓冲区,然后再写入。您太担心“优化”,而您“优化”了错误的事情。如果您遇到性能问题,请使用分析器并查看它们的位置。如果它们确实在这段代码中,那么通过迁移到本地语言而不是试图从 C# 中榨取更多东西,您会获得更好的性能。
  • 为您提供一些数字:超过 10,000 次测试,您的原始代码在平均 1,401,749 nano 秒内保存了 500x500 图像。 Hans 的代码在平均 1,368,200 nano 秒内完成了相同的操作。这些数字之间几乎没有明显差异。写入流的长度只需 31 nano 秒,因此消除它不会获得任何性能。
【解决方案2】:

不要使用 GetBuffer。来自文档:

请注意,缓冲区包含可能未使用的已分配字节。 例如,如果将字符串“test”写入 MemoryStream 对象,GetBuffer返回的缓冲区长度是256,不是 4,有 252 个字节未使用。要仅获取缓冲区中的数据,请使用 ToArray 方法;但是, ToArray 在 记忆。

用途:

 writer.Write(ms.ToArray());

或者如果你在 4.0 中使用 CopyTo 方法:

 ms.CopyTo(netStream);

如果您不在 4.0 中,请检查此项以获取复制流的方法: How do I copy the contents of one stream to another?

【讨论】:

  • 但是,它怎么能和 bmp 一起工作而不是压缩呢?因为 ToArray 将创建一个副本(更慢?)然后 GetBuffer?试过了,速度慢很多。而且我在处理时间中不时得到“Hickups”,从 2ms 到 12ms,GetBuffer 总是 0-2ms。
  • @user2587718 基本上是靠运气。 GetBuffer 和 ToArray 不可互换。
  • 我在 4.5 上,但我可以那样直接写入网络流;S?如果没有二进制读取器/写入器,它如何知道在哪里结束?
  • @user2587718 BinaryWriter 只不过是一些方法的方便包装器。您可以通过写入从 BitConverter.GetBytes 返回的字节来写入长度,然后执行 CopyTo 并获得相同的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多