Jos*_*eph 4 c# multithreading using-statement
我有一个任务,将数据设置为FIFO,然后另一个线程逐个读取FIFO内的数据,然后通过网络发送.调用时数据转换为字节数组FIFO.Add,如下所示:
public byte[] ByteArraySerialize()
{
using (MemoryStream m = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(m))
{
writer.Write((int)this.Opcode);
writer.Write(this.Data);
}
return m.ToArray();
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题:在发送方线程从FIFO中读取数据之前,数据是否可能被破坏或处理?我的问题是了解using内部方法:
这是使用using内部方法的方式可能会导致GC删除MemoryStream,在线程读取数据之前,让我们说在数据进入FIFO后几秒或几分钟后?
有多种方法可以阅读这个问题,但让我们从显而易见的方式开始,即编写方式:
这种方法在方法中使用"使用"可能会导致GC删除内存流,在线程读取数据之前可以说在数据进入FIFO之后几秒钟或者几分钟之后?
不,这不是问题.如果您能够在调用过程中读取数据.ToArray(),那么您已经拥有了数据的副本.如果GC稍后收集流,则阵列将继续运行.为了清楚起见,就GC而言,如果您可以在您调用的位置读取流的内部的良好副本.ToArray(),那么之后该数组将是正常的.根据文档,您将获得内部数据的副本,而不是对其的引用,即便如此,如果您引用了某些内部数据结构,GC将无法收集它.
但是,另一种解释可能是:这段代码有问题吗?
好吧,是的,不.
BinaryWriter当处理编写器实例时,当前实现将处理底层流.这意味着MemoryStream将被处置.
让我复制你的代码并添加一些评论:
public byte[] ByteArraySerialize()
{
using (MemoryStream m = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(m))
{
writer.Write((int)this.Opcode);
writer.Write(this.Data);
}
// m is really disposed here
return m.ToArray();
}
}
Run Code Online (Sandbox Code Playgroud)
这有什么不同吗?好吧,不.在当前的实现中,处理内存流不会以任何方式将其丢弃.但是目前的实施或其未来没有任何保证,这是无证的行为.如果您希望此代码对于.NET的未来版本或修补程序是稳定且值得信赖的,我不会这样写.
因此,我不会这样做.我会重写代码如下:
using (MemoryStream m = new MemoryStream())
using (BinaryWriter writer = new BinaryWriter(m))
{
writer.Write((int)this.Opcode);
writer.Write(this.Data);
writer.Flush();
return m.ToArray();
}
Run Code Online (Sandbox Code Playgroud)
这将要求编写器刷新所有数据,然后在处置该实例之前复制内存流的内部数组.
要么是这样,要么使用重载的构造函数并要求编写器保持流打开:
using (MemoryStream m = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(m, Encoding.UTF8, true))
{
writer.Write((int)this.Opcode);
writer.Write(this.Data);
}
// m is no longer disposed here
return m.ToArray();
}
Run Code Online (Sandbox Code Playgroud)
调用ToArray();有效地复制了您想要的数据.
所以发生在MemStreams上的一切和任何事情都是无关紧要的.
更一般地,只要你的代码可以"看到"一片的数据,那么GC无法回收的那件.
不要过分思考这一点.
假设你曾经使用过:
return m.GetBuffer();
Run Code Online (Sandbox Code Playgroud)
现在您将返回MemStream的内部缓冲区.m将被处置,但仅仅因为你返回它,缓冲区将比它的所有者寿命更长.
| 归档时间: |
|
| 查看次数: |
192 次 |
| 最近记录: |