Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 不使用MemoryStream将WPF字节数组复制到ImageSource_C#_Sql Server_Wpf_Image - Fatal编程技术网

C# 不使用MemoryStream将WPF字节数组复制到ImageSource

C# 不使用MemoryStream将WPF字节数组复制到ImageSource,c#,sql-server,wpf,image,C#,Sql Server,Wpf,Image,我有一个应用程序,可以动态创建WPF图像控件来显示SQL Server数据库表中的图像。显示控件的面板经常被更换。我使用MemoryStream允许控件访问从数据库加载的字节数组。我无法关闭这些流,只要显示图像控件并且仍然显示图像。我担心的是,这些流将一直保持打开状态,直到垃圾收集器开始处理图像控件,并希望关闭这些流。最后,我可能会确保在更换面板之前关闭流或处理图像控件,但我想知道让这些流保持打开是否有问题,以及是否有解决方法 这是我正在使用的代码 public class ImageToSql

我有一个应用程序,可以动态创建WPF图像控件来显示SQL Server数据库表中的图像。显示控件的面板经常被更换。我使用MemoryStream允许控件访问从数据库加载的字节数组。我无法关闭这些流,只要显示图像控件并且仍然显示图像。我担心的是,这些流将一直保持打开状态,直到垃圾收集器开始处理图像控件,并希望关闭这些流。最后,我可能会确保在更换面板之前关闭流或处理图像控件,但我想知道让这些流保持打开是否有问题,以及是否有解决方法

这是我正在使用的代码

public class ImageToSql
{
    private static OpenFileDialog _openFileDialog = new OpenFileDialog();

    static ImageToSql()
    {
        _openFileDialog = new OpenFileDialog();
        _openFileDialog.AddExtension = true;
        _openFileDialog.CheckFileExists = true;
        _openFileDialog.DefaultExt = ".jpg";
        _openFileDialog.Filter = "JPEG files (*.jpg)|*.jpg|All files (*.*)|*.*";
        _openFileDialog.FilterIndex = 1;
        _openFileDialog.Multiselect = false;
    }

    public static BitmapImage LoadImageFromFile(string caption)
    {
        BitmapImage bi = new BitmapImage();

        _openFileDialog.Title = caption;
        if (_openFileDialog.ShowDialog() == true)
        {
            bi.BeginInit();
            bi.StreamSource = File.OpenRead(_openFileDialog.FileName);
            bi.EndInit();
        }

        return bi;
    }

    public static int StoreImage(string connectionString, string sql, string imageParameterName, BitmapImage bitmapImage)
    {
        SqlConnection conn = new SqlConnection(connectionString);
        try
        {
            conn.Open();
            sql += ";SELECT @@IDENTITY";
            using (SqlCommand cmd = new SqlCommand(sql, conn))
            {
                byte[] data = new byte[bitmapImage.StreamSource.Length];
                bitmapImage.StreamSource.Seek(0, SeekOrigin.Begin);
                bitmapImage.StreamSource.Read(data, 0, data.Length);

                cmd.Parameters.Add(imageParameterName, System.Data.SqlDbType.VarBinary, -1).Value = data;
                object obj = cmd.ExecuteScalar();
                return Int32.Parse(obj.ToString());
            }
        }
        finally
        {
            conn.Close();                
        }
    }

    public static BitmapImage RetrieveImage(string connectionString, string sql, string imageIDParameterName, int imageID)
    {
        BitmapImage bi = new BitmapImage();
        SqlConnection conn = new SqlConnection(connectionString);
        try
        {
            conn.Open();
            using (SqlCommand cmd = new SqlCommand(sql, conn))
            {
                cmd.Parameters.Add(imageIDParameterName, System.Data.SqlDbType.Int).Value = imageID;
                byte[] data = (byte[])cmd.ExecuteScalar();

                MemoryStream ms = new MemoryStream(data);
                ms.Seek(0, SeekOrigin.Begin);
                bi.BeginInit();
                bi.StreamSource = ms;
                bi.EndInit();
            }
        }
        finally
        {
            conn.Close();
        }

        return bi;
    }
}
下面是如何调用此代码。“\u fileImage”和“\u sqlImage”是我的测试窗口上的图像控件。有一次,我在“LoadImageFromFile”中使用一个流从磁盘读取文件,并且认为我能够在图像控件中显示图像的同时关闭该流。所以,MemoryStream似乎有点特别

        BitmapImage bi = ImageToSql.LoadImageFromFile("Select Image to Save");
        _fileImage.Source = bi;

        int imageID = ImageToSql.StoreImage(connString,
            "INSERT INTO PV_Image (Description, Image) VALUES ('Some Image', @pImage)",
            "@pImage", bi);

        _sqlImage.Source = ImageToSql.RetrieveImage(connString, 
            "SELECT Image FROM PV_Image WHERE ImageID = @pImageID", 
            "@pImageID", imageID);

一旦使用内存流,您可以使用以下使用模式来处置它:

using (Stream stream = new MemoryStream(data))
{
    BitmapImage image = new BitmapImage():
    stream.Position = 0;
    image.BeginInit();
    image.CacheOption = BitmapCacheOption.OnLoad;
    image.StreamSource = stream;
    image.EndInit();
    image.Freeze();
    return image;
}

好的,我可能已经在SqlConnection上使用了一个“using”来自动关闭它了。旧习难改。谢谢。所以,诀窍是我需要设置缓存选项,然后冻结图像。我必须做一些研究来了解原因。现在,我更愿意关闭流,然后让它们保持打开状态,以便稍后由我的代码或GC关闭。from msdn:如果希望关闭用于创建BitmapImage的流,请将CacheOption设置为BitmapCacheOption.OnLoad。默认的OnDemand缓存选项保留对流的访问,直到需要映像并且垃圾回收器处理清理。此外:bitmapImage在冻结时是可冻结的,它将变为不可变,并且具有性能优势(无需更改通知),并且可以跨线程访问。它似乎还可以防止某些内存泄漏。