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"
初めて正常に動作し、ファイルが宛先フォルダーにコピーされています。

ただし、このコードが次の値で実行される 2 回目:
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);

NotifyPropertyChanged画像を読み込んだ後、WPF が変更を認識するイベントをスローすることを忘れないでください... ;-)

于 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 の質問から取得されます

于 2012-06-27T14:09:31.580 に答える