我在WPF应用程序中进行图像读取/复制操作。请看下面这段代码:
try
{
if (sourceDir != "")
File.Copy(sourceDir, Path.Combine(backupDir, ecode + ".jpg"), true);
}
catch (Exception exx)
{
MessageBox.Show(exx.ToString());
}
现在让我们解释一下场景的问题:
第一次执行此代码时,sourceDir
和Path.Combine(backupDir, ecode + ".jpg")
值为:
sourceDir =“C:\ Users \ Public \ Pictures \ Sample Pictures \ Desert.jpg”
Path.Combine(backupDir,ecode +“.jpg”) =“D:\ IEPL-archives-不要修改\ DATA \ 654.jpg”
它第一次工作正常,文件被复制到其目标文件夹。
但这是第二次使用以下值执行此代码时:
sourceDir =“C:\ Users \ Public \ Pictures \ Sample Pictures \ Penguins.jpg”
Path.Combine(backupDir,ecode +“.jpg”) =“D:\ IEPL-archives-不要修改\ 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;
}
请建议我如何修改代码以避免这种冲突? 感谢
答案 0 :(得分: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;
答案 1 :(得分:1)
根据之前的评论,文件句柄可能会在UI中显示后保持打开状态。所以我想在你第一次复制它然后显示它之后,句柄可能永远不会被关闭。
并且,当您继续覆盖相同的目标图像名称时,代码会抛出上述异常。
例如,如果您正在使用某种Image.FromFile()
方法,情况就是如此。这确实会使句柄保持打开状态直到应用程序结束......
[更新问题后编辑]
您需要将缓存选项更改为:
如果要关闭a,请将CacheOption设置为BitmapCacheOption.OnLoad 用于创建BitmapImage的流。默认的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);
加载图片后,不要忘记抛出NotifyPropertyChanged
事件WPF识别出更改...; - )
答案 2 :(得分:0)
我认为第一步是确定哪个进程锁定了您的文件。为此,我建议使用Handle from Sysinternals。一旦异常提升,请使用该应用程序将其检出。
如果其他答案建议的延迟足以复制文件,则可能是您无法使用该工具进行检查。在这种情况下,您需要一个自动解决方案来确定锁定文件的人员。你可以使用WMI来做到这一点。
现在,我的猜测是你的进程正在锁定文件,这意味着来自的某种bug或意外行为。File.Copy
编辑:好的,现在我们知道你是打开文件的人......
答案 3 :(得分: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代码取自this SO question