Reputation: 2924
I am doing image Read/Copy operations in WPF application. Please look at following piece of code:
try
{
if (sourceDir != "")
File.Copy(sourceDir, Path.Combine(backupDir, ecode + ".jpg"), true);
}
catch (Exception exx)
{
MessageBox.Show(exx.ToString());
}
Now let explain problem with a scenario:
First time when this code executes the sourceDir
and Path.Combine(backupDir, ecode + ".jpg")
values are:
sourceDir="C:\Users\Public\Pictures\Sample Pictures\Desert.jpg"
Path.Combine(backupDir, ecode + ".jpg")="D:\IEPL-archives-Do not Modify\DATA\654.jpg"
It works fine for the first time and file is being copied to its destination folder.
But for the second time when this code executes with following values:
sourceDir="C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg"
Path.Combine(backupDir, ecode + ".jpg")="D:\IEPL-archives-Do not Modify\DATA\654.jpg"
It throws following exception:
I am also displaying same image in UI, that is causing this exception. Here is the code which displays the image in 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;
}
Please suggest how can i modify the code so that this conflict will not arise? Thanks
Upvotes: 2
Views: 2484
Reputation: 4632
According to the previous comments it might be that the file handle stays open after displaying it in the UI. So I guess that after you copy it for the first time and then display it, the handle possibly never gets closed.
And, as you keep overwiting the same target image name, the code then throws the mentioned exception.
This would be exactly the case if you are using something Image.FromFile()
methood, for example. This indeed keeps the handles open until the end of the application...
[EDIT after you updated the question]
You need to change the caching options to:
From the MSDN documentation:
Set the CacheOption to BitmapCacheOption.OnLoad if you wish to close a stream used to create the BitmapImage. The default OnDemand cache option retains access to the stream until the image is needed, and cleanup is handled by the garbage collector.
(Code copied from documentation.)
// 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);
And after loading the image, do not forget to throw the NotifyPropertyChanged
event the WPF recognizes the change... ;-)
Upvotes: 1
Reputation: 30718
You can load the file into memory, and then can create BitmapImage from in memory data.
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;
}
byte array to BitmapImage code is taken from this SO question
Upvotes: 0
Reputation: 8564
I think that the first step is to determine which process has locked your file. To do that, I recommend using Handle from Sysinternals. As soon as the exception raises, use the app to check it out.
If the delay suggested by the other answer is enough to copy the file, it may be that you can't really use the tool to check that. In this case, you need an automated solution to determine who is locking the file. You can use WMI to do that.
Now, my guess is that your process is locking the file, which would mean some sort of bug or unintended behavior from .File.Copy
EDIT: Ok, now we know you are the one opening the file...
Upvotes: 0
Reputation: 2573
You should load the image into memory using BitmapCacheOption.OnLoad
. That will release the lock on the file.
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;
Upvotes: 4