2012-06-27 3 views
2

Я выполняю операции чтения/копирования изображений в приложении 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-архивы-не Изменить \ DATA \ 654.jpg»
Это работает отлично в первый раз, и файл копируется в папку назначения.

Но во второй раз, когда этот код выполняется со следующими значениями:
SourceDir = "C: \ Users \ Public \ Pictures \ Sample Pictures \ Penguins.jpg"
Path.Combine (backupDir, ecode + ".jpg ") =" D: \ IEPL-архивы, не Modify \ DATA \ 654.jpg"
Он бросает следующее исключение:

enter image description here

Я также отображаются в то же изображение Пользовательский интерфейс, то есть cau петь это исключение. Вот код, который отображает изображение в пользовательском интерфейсе:

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; 
    } 

Пожалуйста, подсказывает, как я могу изменить код так, чтобы этот конфликт не возникнет? Thanks

+0

Является ли изображение (D: \ IEPL-архивы, не Modify \ DATA \ 654.jpg) показывается в интерфейсе? – ekholm

+0

@ekholm yes Это изображение показано в UI одновременно. – Azeem

+0

Оба 'Path.Combine (backupDir, ecode +" .jpg ")' имеют ** то же самое местоположение целевого изображения **. Это предназначено? Если нет, это уже может послужить причиной вашего исключения ... –

ответ

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; 
+0

после обновления с помощью этого кода теперь нет исключения, но файл изображения не обновляется/не заменяется новым! – Azeem

+0

Неужели вы пытались с BitmapCacheOption.None? –

+0

@SivaGopal BitmapCacheOption.None не работает. – Azeem

0

Я думаю, что первый шаг - определить, какой процесс заблокировал ваш файл. Для этого я рекомендую использовать Handle from Sysinternals. Как только возникнет исключение, используйте приложение, чтобы проверить его.

Если задержки, предложенные другим ответом, достаточны для копирования файла, возможно, вы не можете использовать этот инструмент, чтобы проверить это. В этом случае вам необходимо автоматическое решение, чтобы определить, кто блокирует файл. Вы можете использовать WMI для этого.

Теперь, я думаю, что ваш процесс является блокировка файла, который будет означать какой-то ошибки или непреднамеренного поведения от File.Copy .

EDIT: Хорошо, теперь мы знаем, ты один открыть файл ...

1

Согласно предыдущим комментариям это может быть, что дескриптор файла остается открытым после его отображения в пользовательском интерфейсе. Поэтому я предполагаю, что после того, как вы скопируете его в первый раз, а затем отобразите его, ручка, возможно, никогда не будет закрыта.

И, поскольку вы сохраняете одно и то же имя целевого изображения, код затем выдает указанное исключение.

Это будет именно так, если вы используете что-то Image.FromFile() methood, например.Это действительно держит ручки открытыми до конца приложения ...

[EDIT после обновленный вопрос]

Вам нужно изменить параметры кэширования для:

От MSDN documentation:

Установите CacheOption в BitmapCacheOption.OnLoad, если вы хотите закрыть поток , используемый для создания BitmapImage. По умолчанию опция OnDemand cache сохраняет доступ к потоку до тех пор, пока изображение не понадобится, а очистка обрабатывается сборщиком мусора.

(код копируется из документации.)

// 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 событие МОФ распознает изменение ... ;-)

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

Смежные вопросы