C# Wpf-将画布另存为图像并将图像加载到画布。错误:";正在被另一个过程使用”;

C# Wpf-将画布另存为图像并将图像加载到画布。错误:";正在被另一个过程使用”;,c#,wpf,canvas,C#,Wpf,Canvas,我正在尝试将包含一些形状的画布保存为图像(*.jpg,*.bmp,*.png),然后再次将该图像加载到画布 当我单击“保存按钮”,然后单击“加载按钮”,然后再次单击“保存按钮”时,我出现以下故障: 进程无法访问文件“H:\VisualC\HK5\LT Win\ForTesting\TestSaveCanvasToBitmap\bin\Debug\TestImage.bmp”,因为另一进程正在使用该文件。 似乎有一个文件流处于打开状态,但尚未关闭。 谁能给我解释一下吗 提前谢谢 这是我的密码 pu

我正在尝试将包含一些形状的画布保存为图像(*.jpg,*.bmp,*.png),然后再次将该图像加载到画布

当我单击“保存按钮”,然后单击“加载按钮”,然后再次单击“保存按钮”时,我出现以下故障:

进程无法访问文件“H:\VisualC\HK5\LT Win\ForTesting\TestSaveCanvasToBitmap\bin\Debug\TestImage.bmp”,因为另一进程正在使用该文件。

似乎有一个文件流处于打开状态,但尚未关闭。 谁能给我解释一下吗

提前谢谢

这是我的密码

public void SaveImage(Canvas canvas, int width, int height, string filePath)
        {
            Rect bounds = VisualTreeHelper.GetDescendantBounds(canvas);
            double dpi = 96d;
            RenderTargetBitmap rtb = new RenderTargetBitmap(width, height, dpi, dpi, System.Windows.Media.PixelFormats.Default);

            DrawingVisual dv = new DrawingVisual();
            using (DrawingContext dc = dv.RenderOpen())
            {
                VisualBrush vb = new VisualBrush(canvas);
                dc.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
            }

            rtb.Render(dv);

            BmpBitmapEncoder image = new BmpBitmapEncoder();
            image.Frames.Add(BitmapFrame.Create(rtb));

            using (Stream fs = File.Create(filePath))
            {
                image.Save(fs);
                fs.Close();
            }
        }
        private void btnSave_Click(object sender, RoutedEventArgs e)
        {
            int width = (int)myCanvas.ActualWidth;
            int height = (int)myCanvas.ActualHeight;
            string filePath = "TestImage.bmp";

            SaveImage(myCanvas, width, height, filePath);
        }

        private void btnLoad_Click(object sender, RoutedEventArgs e)
        {
            Uri uri = new Uri(@"TestImage.bmp", UriKind.Relative);

            BitmapImage bmi = new BitmapImage(uri);

            ImageBrush brush = new ImageBrush();
            brush.ImageSource = bmi;

            myCanvas.Background = brush;
        }

该文件仍处于锁定状态,因为您正在笔刷中直接引用它。如果不可靠地再现问题,就不可能确定最佳解决方案是什么。但最有可能的情况是,如果在画笔中使用位图对象之前克隆该对象,当您再次尝试保存到该文件时,它将被释放

例如:

BitmapImage bmi = new BitmapImage(uri).Clone();

不幸的是,我不知道有什么好的确定方法可以强制关闭
BitmapImage
对象,尤其是它对文件的引用。您可以调用
Freeze()
,它可能会断开与文件的连接(但我还没有尝试过)。或者,强制垃圾收集应该可以工作(即调用
GC.Collect()
)。

当您加载映像并试图通过覆盖来保存它时,引用其物理文件的映像仍被应用程序使用,因此无法覆盖该文件。我猜当您从URI创建
BitmapImage
对象时,附加到文件的流总是打开的。尝试像这样更改加载方法

private void btnLoad_Click(object sender, RoutedEventArgs e)
{
  MemoryStream memoStream = new MemoryStream();

  using (FileStream fs = File.OpenRead("TestImage.bmp"))
  {
    fs.CopyTo(memoStream);

    BitmapImage bmi = new BitmapImage();

    bmi.BeginInit();

    bmi.StreamSource = memoStream;

    bmi.EndInit();

    ImageBrush brush = new ImageBrush(bmi);

    myCanvas.Background = brush;

    fs.Close();
  }
}

我们的想法是将文件流复制到内存流,这样图像对象将生活在内存中,不再依赖文件。

谢谢您的帮助。我已经用另一种方法解决了我的问题。很好的解释。我已经用这个解决了我的问题,谢谢。把这个记下来作为一个答案吧?