wpf 图像文件副本,正在被另一个进程使用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18167280/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:25:11  来源:igfitidea点击:

Image file copy, is being used by another process

c#wpfimagefileprocess

提问by Lai32290

I'm trying create a user perfil edit window, in this window has a Image control
When I selected a image file, it will show in this Image control and copy this file at my image folder, first time is all right, but second time, it show a error

我正在尝试创建一个用户 perfil 编辑窗口,在这个窗口中有一个图像控件
当我选择一个图像文件时,它会显示在这个图像控件中并将这个文件复制到我的图像文件夹中,第一次没问题,但第二次,显示错误

"The process cannot access the file 'C:\1.jpg' because it is being used by another process."

“该进程无法访问文件 'C:\1.jpg',因为它正被另一个进程使用。”

I think it is because my Image control is using this file, so, I don't know what can I do

我想是因为我的 Image 控件正在使用这个文件,所以,我不知道我该怎么办

private void Select_Click(object sender, RoutedEventArgs e)
{
    OpenFileDialog od = new OpenFileDialog();
    if (od.ShowDialog() == true)
    {
        string imageLocal = @"C:/1.jpg";
        File.Copy(od.FileName, imageLocal, true);
        image1.Source = new BitmapImage(new Uri(imageLocal));
    }
}

回答by Gayot Fow

If you want to load and display an image, and keep the file amenable to operations in the file system (like reloading it or moving it to another directory), the Uri constructor will not work because (as you point out), the BitmapImage class hangs on to the file handle.

如果要加载和显示图像,并使文件适合文件系统中的操作(例如重新加载或将其移动到另一个目录),则 Uri 构造函数将不起作用,因为(如您所指出的)BitmapImage 类挂在文件句柄上。

Instead, use a method like this...

相反,使用这样的方法......

    private static BitmapImage ByStream(FileInfo info)
    {   //http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/dee7cb68-aca3-402b-b159-2de933f933f1
        try
        {
            if (info.Exists)
            {
                // do this so that the image file can be moved in the file system
                BitmapImage result = new BitmapImage();
                // Create new BitmapImage   
                Stream stream = new MemoryStream(); // Create new MemoryStream   
                Bitmap bitmap = new Bitmap(info.FullName);
                // Create new Bitmap (System.Drawing.Bitmap) from the existing image file 
                                             (albumArtSource set to its path name)   
                bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
                // Save the loaded Bitmap into the MemoryStream - Png format was the only one I 
                              tried that didn't cause an error (tried Jpg, Bmp, MemoryBmp)   
                bitmap.Dispose(); // Dispose bitmap so it releases the source image file   
                result.BeginInit(); // Begin the BitmapImage's initialisation   
                result.StreamSource = stream;
                // Set the BitmapImage's StreamSource to the MemoryStream containing the image   
                result.EndInit(); // End the BitmapImage's initialisation   
                return result; // Finally, set the WPF Image component's source to the 
                                BitmapImage  
            }
            return null;
        }
        catch
        {
            return null;
        }
    }

This method takes a FileInfo and returns a BitmapImage which you can display and simultaneously move it to another directory or display it again.

此方法接受一个 FileInfo 并返回一个 BitmapImage,您可以显示它并同时将其移动到另一个目录或再次显示它。

A much simpler method, copied from another answer below, is this:

从下面的另一个答案复制的更简单的方法是:

public static BitmapImage LoadBitmapImage(string fileName)
{
    using (var stream = new FileStream(fileName, FileMode.Open))
    {
        var bitmapImage = new BitmapImage();
        bitmapImage.BeginInit();
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.StreamSource = stream;
        bitmapImage.EndInit();
        bitmapImage.Freeze(); 
        return bitmapImage;
    }
}

回答by Clemens

The method shown below loads a BitmapImage from file and immediately closes the file after loading. Note that it is necessary to set the BitmapCacheOption.OnLoadflag when the source stream is closed right after EndInit.

下面显示的方法从文件加载 BitmapImage 并在加载后立即关闭文件。请注意,BitmapCacheOption.OnLoad当源流在 之后立即关闭时,有必要设置标志EndInit

public static BitmapImage LoadBitmapImage(string fileName)
{
    using (var stream = new FileStream(fileName, FileMode.Open))
    {
        var bitmapImage = new BitmapImage();
        bitmapImage.BeginInit();
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.StreamSource = stream;
        bitmapImage.EndInit();
        bitmapImage.Freeze(); // just in case you want to load the image in another thread
        return bitmapImage;
    }
}

This code will work for any image format that is supported by WPF. When passing the image file content as stream to the StreamSourceproperty, WPF will automatically create the appropriate decoder.

此代码适用于 WPF 支持的任何图像格式。将图像文件内容作为流传StreamSource递给属性时,WPF 将自动创建适当的解码器。

回答by sma6871

Very simple solution:

非常简单的解决方案:

System.GC.Collect();  
System.GC.WaitForPendingFinalizers();

File.Copy(od.FileName, imageLocal, true);