我想知道为什么Visual Studio代码分析会用这一小段代码发出警告:
byte[] data = File.ReadAllBytes("myImage.png");
using (MemoryStream mem = new MemoryStream(data))
using (Bitmap bmp = new Bitmap(mem))
{
// do something with the bitmap
}
错误是:
对象'mem'可以在方法中多次处理...要避免 生成一个不应该调用的System.ObjectDisposedException 在物体上多次处理。
如何解决这个问题? (是的,我可以直接从文件加载位图,但在我的真实项目中,我有自己的文件格式,其中多个图像保存到一个文件中,因此我需要MemoryStream
来加载来自特定范围的数据文件)
答案 0 :(得分:6)
问题是Bitmap
取得了它在构造函数中给出的流的所有权。 它将处理流 - 您不需要。所以你需要的只是:
using (Bitmap bmp = new Bitmap(new MemoryStream(data)))
{
// do something with the bitmap
}
答案 1 :(得分:1)
关于第二次可靠性警告,似乎在发生这种情况时,无论您做什么,代码分析都会抱怨CA2000 或 CA2202。对此有多处抱怨,here's one for your enjoyment.
为了看看是否特别使用语法,我将使用扩展到try catch块并获得相同的行为。
class Program
{
static void Main(string[] args)
{
byte[] data = {};
//using (Bitmap bitmap = new Bitmap(new MemoryStream(data)))
//{ }
MemoryStream mem = null;
Bitmap bitmap = null;
try
{
mem = new MemoryStream(data);
bitmap = new Bitmap(mem);
}
catch (Exception)
{
throw;
}
finally
{
if (null!= bitmap ) bitmap.Dispose();
// commenting this out will provoke a CA2000.
// uncommenting this will provoke CA2202.
// so pick your poison.
// if (null != mem) mem.Dispose();
}
}
}
编辑:正如你(Jaska)指出的那样,有一条来自微软的关于在Bitmap的使用块中标记内存流意图的说明:
class Program
{
static void Main(string[] args)
{
byte[] data = new byte[1000];
MemoryStream mem = null;
try
{
mem = new MemoryStream(data);
using (Bitmap bmp = new Bitmap(mem))
{
mem = null; // <-- this line will make both warning go away
}
}
finally
{
if (mem != null)
{
mem.Dispose();
}
}
}
}
我很高兴看到这个有效,但同时它比在位图的构造函数中使用匿名内存流有点丑陋。好吧。
答案 2 :(得分:1)
Reacher-Gilt与ms-page的链接引导我找到解决方案,这将使两个警告消失:
byte[] data = new byte[1000];
MemoryStream mem = null;
try
{
mem = new MemoryStream(data);
using (Bitmap bmp = new Bitmap(mem))
{
mem = null; // <-- this line will make both warning go away
}
}
finally
{
if (mem != null)
{
mem.Dispose();
}
}
答案 3 :(得分:0)
一旦你输入第二个using语句,你的Bitmap将“消耗”内存流 - 它对内存流负责,包括它的处理。这是明智的,如果你考虑一下你的用法:你是否希望在你的Bitmap构造函数中使用它之后(或期间)访问mem
?我可能不会说。
答案是将两个使用语句合并在一起:using (Bitmap bitmap = new Bitmap(new MemoryStream(data)))
。这应该照顾CA警告。