2

我正在 WPF 应用程序中执行图像读取/复制操作。请看以下代码:

try
{
  if (sourceDir != "")
    File.Copy(sourceDir, Path.Combine(backupDir, ecode + ".jpg"), true);
}
catch (Exception exx)
{
    MessageBox.Show(exx.ToString());
}

现在让我们用一个场景来解释问题:
第一次执行此代码时sourceDirPath.Combine(backupDir, ecode + ".jpg")值是:
sourceDir ="C:\Users\Public\Pictures\Sample Pictures\Desert.jpg"
Path.Combine(backupDir, ecode + ".jpg" ) ="D:\IEPL-archives-Do not Modify\DATA\654.jpg"
它第一次工作正常,文件被复制到其目标文件夹。

但是第二次使用以下值执行此代码时:
sourceDir ="C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg"
Path.Combine(backupDir, ecode + ".jpg") ="D:\ IEPL-archives-Do not Modify\DATA\654.jpg"
它抛出以下异常:

在此处输入图像描述

我也在 UI 中显示相同的图像,这导致了这个异常。这是在 UI 中显示图像的代码:

image1.Source = new BitmapImage(new Uri(GetPicture(txtBarcode.Text), UriKind.RelativeOrAbsolute));
private string GetPicture(string _eid)
    {
        string picname = "";
        if (File.Exists(@"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".jpg"))
            picname = @"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".jpg";
        else if (File.Exists(@"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".jpeg"))
            picname = @"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".jpeg";
        else if (File.Exists(@"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".png"))
            picname = @"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".png";
        else if (File.Exists(@"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".gif"))
            picname = @"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".gif";
        else if (File.Exists(@"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".JPG"))
            picname = @"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".JPG";
        else if (File.Exists(@"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".JPEG"))
            picname = @"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".JPEG";
        else if (File.Exists(@"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".PNG"))
            picname = @"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".PNG";
        else if (File.Exists(@"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".GIF"))
            picname = @"D:\IEPL-archives-Do not Modify\DATA\" + _eid + ".GIF";
        else
            picname = @"Images\defaultPicture.jpg";
        return picname;
    }

请建议我如何修改代码以免出现这种冲突?谢谢

4

4 回答 4

4

您应该使用BitmapCacheOption.OnLoad. 这将释放文件上的锁定。

BitmapImage bi = new BitmapImage();
bi.BeginInit();

bi.CacheOption = BitmapCacheOption.OnLoad;
bi.UriSource = new Uri(GetPicture(txtBarcode.Text), UriKind.RelativeOrAbsolute);

// End initialization.
bi.EndInit();
image1.Source = bi;
于 2012-06-27T14:00:22.203 回答
1

根据之前的评论,可能是文件句柄在 UI 中显示后保持打开状态。所以我猜在你第一次复制它然后显示它之后,句柄可能永远不会关闭。

而且,当您不断覆盖相同的目标图像名称时,代码会引发上述异常。

例如,如果您使用某种方法Image.FromFile(),情况正是如此。这确实使句柄保持打开状态,直到应用程序结束......

[更新问题后编辑]

您需要将缓存选项更改为:

MSDN 文档

如果您希望关闭用于创建 BitmapImage 的流,请将 CacheOption 设置为 BitmapCacheOption.OnLoad。默认的 OnDemand 缓存选项保留对流的访问,直到需要图像为止,并且清理由垃圾收集器处理。

(从文档中复制的代码。)

// Define a BitmapImage.
Image myImage = new Image();
BitmapImage bi = new BitmapImage();

// Begin initialization.
bi.BeginInit();

// Set properties.
bi.CacheOption = BitmapCacheOption.OnLoad; // <-- This is the important one
bi.CreateOptions = BitmapCreateOptions.DelayCreation;
bi.DecodePixelHeight = 125;
bi.DecodePixelWidth = 125;
bi.Rotation = Rotation.Rotate90;
MessageBox.Show(bi.IsDownloading.ToString());
bi.UriSource = new Uri("smiley.png", UriKind.Relative);

// End initialization.
bi.EndInit();
myImage.Source = bi;
myImage.Stretch = Stretch.None;
myImage.Margin = new Thickness(5);

加载图像后,不要忘记抛出NotifyPropertyChangedWPF 识别更改的事件... ;-)

于 2012-06-27T14:04:03.560 回答
0

我认为第一步是确定哪个进程锁定了您的文件。为此,我建议使用来自 Sysinternals 的 Handle。一旦出现异常,请使用该应用程序进行检查。

如果其他答案建议的延迟足以复制文件,则可能是您无法真正使用该工具进行检查。在这种情况下,您需要一个自动化的解决方案来确定谁在锁定文件。您可以使用 WMI 来做到这一点。

现在,我的猜测是您的进程正在锁定文件,这意味着来自File.Copy.

编辑:好的,现在我们知道您是打开文件的人...

于 2012-06-27T14:02:03.843 回答
0

您可以将文件加载到内存中,然后可以从内存数据中创建 BitmapImage。

    BitmapImage GetImage( String filepath)
    {
        byte[] rawImageBytes = File.ReadAllBytes(filepath);
        BitmapImage imageSource = null;

        try
        {
            using ( MemoryStream stream = new MemoryStream( rawImageBytes  ) )
            {
                stream.Seek( 0, SeekOrigin.Begin );
                BitmapImage b = new BitmapImage();
                b.SetSource( stream );
                imageSource = b;
            }
        }
        catch ( System.Exception ex )
        {
        }

        return imageSource;
    }

字节数组到 BitmapImage 代码取自这个 SO question

于 2012-06-27T14:09:31.580 回答