C# 多次操作提供的流有什么风险
用户给定一个流,我们希望他们通过典型的使用C# 多次操作提供的流有什么风险,c#,C#,用户给定一个流,我们希望他们通过典型的使用 using(var stream = new MemoryStream()) { MyMethod(stream); } 在处理流之后复制回流是否存在任何风险。具体来说,我们有一个填充数据的方法,但是我们有一个对数据排序的条件需求。所以MyMethod是这样的: void MyMethod(Stream stream, bool sort = false) { //Stream is populated stream.Posi
using(var stream = new MemoryStream())
{
MyMethod(stream);
}
在处理流之后复制回流是否存在任何风险。具体来说,我们有一个填充数据的方法,但是我们有一个对数据排序的条件需求。所以MyMethod是这样的:
void MyMethod(Stream stream, bool sort = false)
{
//Stream is populated
stream.Position = 0;
if(sort)
{
Sort(stream);
}
}
void Sort(Stream stream)
{
using(var sortedStream = new MemoryStream)
{
//Sort per requirements into the new sorted local stream
sortedStream.Position = 0;
//Is this safe? Any risk of losing data or memory leak?
sortedStream.CopyTo(stream);
}
}
需要注意的是,我们正在填充用户提供的流,然后将其排序为本地流。由于本地流属于本地方法,因此它被清理,但反过来,我们不能清理提供的流,而是希望用本地结果填充它
重申我的问题,这有什么问题吗?是否存在垃圾数据在流中的风险或我没有想到的其他问题?我不知道为什么在将其插入流之前不对其进行排序,或者为什么在访问看起来是随机访问时使用流,但从技术上讲,这是可以的。你能做到。它将起作用。给定流是否支持移动位置并在其自身上重新写入数据取决于特定流。有些人支持,有些人不支持。并不是所有的流都可以改变它们的位置,也不是所有的流都可以写,也不是所有的流都可以覆盖现有的数据,有些流可以做所有这些事情 如果您做了任何不受支持的事情,行为良好的流不应该泄漏资源;它应该只是抛出一个异常,但从技术上讲,自定义流可以做它想做的任何事情,因此您可以编写自己的流,在更改位置时泄漏资源。当然,在这一点上,泄漏资源的错误在该流的实现中,而不是在对流中的数据进行排序的代码中。这里显示的代码只需要担心在执行不受支持的操作时流引发异常。是一个抽象类,有许多不同的实现。并非所有流都可以写入,因此在某些情况下,代码可能无法按预期工作,或者可能崩溃
sortedStream.Position = 0;
sortedStream.CopyTo(stream);
您需要事先检查和属性:
if (sortedStream.CanSeek & stream.CanWrite)
{
sortedStream.Position = 0;
sortedStream.CopyTo(stream);
}
else
{
// not supported
}
只要一切都在一个线程中,就没有问题。如果您有多个线程,那么您需要执行某种同步,以确保在仍在使用时不会将位置设置回零。这就是为什么存在不可变类型、只读集合等,您可以在没有风险的情况下公开这些类型。通过传递可变对象,您可以使用它做任何事情,所以是的,它应该是可以的。不要担心,如果你做错了什么,你会得到一个异常。@jdweng承认流决不是线程安全的,这里写的任何东西都不应该有问题,因为它都是本地化的。没有办法在错误的线程上交换位置。如果存在线程交换,上下文开关将正确地处理所有注册的本地变量。未对其进行排序的原因是费用。系统用户可能不关心要排序的数据。数据不是随机访问,而是由一个上面有“MyMethod”的对象保存的。我没有把我的问题和所有这些细节混为一谈,而是把它归结为我们面临的核心问题。