0

我想知道为什么 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,您不应在对象上多次调用 Dispose。

以及如何纠正这一点?(是的,我可以直接从文件加载位图,但在我的实际项目中,我有自己的文件格式,其中多个图像保存到一个文件中,因此我需要MemoryStream从文件中的特定范围加载数据)

4

4 回答 4

6

问题是它Bitmap拥有它在其构造函数中给出的流的所有权。会处理流 - 你不需要。所以你只需要:

using (Bitmap bmp = new Bitmap(new MemoryStream(data)))            
{
     // do something with the bitmap
}
于 2012-06-29T19:21:28.407 回答
1

关于第二个可靠性警告,似乎当这种情况发生时,无论您做什么,代码分析都会向 CA2000或CA2202 抱怨。对此有很多抱怨,这里有一个供您欣赏。

只是为了看看它是否特别适用于 using 语法,我将 using 扩展为 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)所指出的,Microsoft 有一条关于在位图的 using 块中标记有关内存流的意图的说明:

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();
                }
            } 
        } 
    }

我很高兴看到这行得通,但同时它比在位图的构造函数中使用匿名内存流有点难看。呃,好吧。

于 2012-06-29T20:15:38.953 回答
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();
            }
        } 
于 2012-06-29T20:42:10.070 回答
0

一旦你输入第二个 using 语句,你的 Bitmap 将“消耗”内存流——它负责内存流,包括它的处理。mem这是明智的,如果您考虑一下您的用法:您是否希望在您在位图的构造函数中使用它之后(或期间)访问其他东西?我会说可能不会。

答案是将两个 using 语句合并在一起:using (Bitmap bitmap = new Bitmap(new MemoryStream(data))). 那应该照顾CA警告。

于 2012-06-29T19:30:39.697 回答