4

そこで、縦横比に応じて壁紙をフォルダーにきれいに分類するための簡単なアプリケーションを作成していました。(FileInfo.MoveTo() を使用して) 実際にファイルを移動しようとするまで、すべてがスムーズに進んでいます。アプリケーションが例外をスローします。

System.IO.IOException 別のプロセスによって使用されているため、プロセスはファイルにアクセスできません。

唯一の問題は、その特定のファイルを開いているコンピューターで他のプロセスが実行されていないことです。おそらく、ファイルの使用方法が原因で、別のスレッドの内部システムサブルーチンか、ファイルを移動しようとしたときにファイルが開かれている可能性があると思いました。案の定、その数行上に、読み取り用にファイルを開くイベントを呼び出すプロパティを設定しました。少なくともその一部は非同期で発生すると思います。とにかく同期的に実行する方法はありますか? そのプロパティを変更するか、コードの多くを書き直す必要があります。

関連するコードの一部を以下に示します。Visual C# のデフォルト名が下手なのは許してください。これは、まだリリース品質のソフトウェアではありません。

private void button1_Click(object sender, EventArgs e)
{
    for (uint i = 0; i < filebox.Items.Count; i++)
    {
        if (!filebox.GetItemChecked((int)i)) continue;

        //This calls the selectedIndexChanged event to change the 'selectedImg' variable
        filebox.SelectedIndex = (int)i;

        if (selectedImg == null) continue;

        Size imgAspect = getImgAspect(selectedImg);

        //This is gonna be hella hardcoded for now
        //In the future this should be changed to be generic
        //and use some kind of setting schema to determine
        //the sort/filter results

        FileInfo file = ((FileInfo)filebox.SelectedItem);

        if (imgAspect.Width == 8 && imgAspect.Height == 5)
        {
            finalOut = outPath + "\\8x5\\" + file.Name;
        }
        else if (imgAspect.Width == 5 && imgAspect.Height == 4)
        {
            finalOut = outPath + "\\5x4\\" + file.Name;
        }
        else
        {
            finalOut = outPath + "\\Other\\" + file.Name;
        }

        //Me trying to tell C# to close the file
        selectedImg.Dispose();
        previewer.Image = null;

        //This is where the exception is thrown
        file.MoveTo(finalOut);
    }
}

//The suspected event handler
private void filebox_SelectedIndexChanged(object sender, EventArgs e)
{
    FileInfo selected;
    if (filebox.SelectedIndex >= filebox.Items.Count || filebox.SelectedIndex < 0) return;
    selected = (FileInfo)filebox.Items[filebox.SelectedIndex];

    try
    {
        //The suspected line of code
        selectedImg = new Bitmap((Stream)selected.OpenRead());
    }
    catch (Exception) { selectedImg = null;  }

    if (selectedImg != null)
        previewer.Image = ResizeImage(selectedImg, previewer.Size);
    else
        previewer.Image = null;
}

私は長い修正を念頭に置いていますが(おそらくそれはおそらくより効率的です)、それでもまだ多くの問題があります:/

どんな助けでも大歓迎です。

4

3 に答える 3

0

新しい答え:

OpenRead() を実行する行を見ました。明らかに、これはファイルをロックします。ビットマップがエラーになるため、ストリームを破棄できないため、ストリームの代わりにファイルパスを提供することをお勧めします。

私があなたのコードで見ているもう1つの悪い習慣は、FileInfoへのバインドです。データ転送オブジェクト/値オブジェクトを作成し、このタイプのコレクション (コントロールに表示する必要があるプロパティを持つオブジェクト) にバインドすることをお勧めします。これは、ファイルのロックを回避するために役立ちます。

一方、いくつかのトリックを行うことができます。画像サイズが実際のものよりも極端に小さくなるように圧縮して画面解像度の画像にストレッチして表示し、「HQで表示」というボタンを提供してみませんか? これにより、HD 画像のプリロードの問題が解決されるはずです。ユーザーが「Show in HQ」ボタンをクリックすると、その画像がメモリにロードされ、これが閉じられると破棄されます。

これはあなたににあってます?

私が間違っていなければ、FileInfo はどのファイルもブロックしません。あなたはそれを開いているのではなく、そのメタデータを読んでいます。

一方、アプリケーションが画像を表示する場合は、メモリに表示されているものに移動し、メモリ ストリームからフォームにロードする必要があります。

ファイル ストリームを開き、そのバイトを読み取り、それらをメモリ ストリームに移動して、そのファイルに対するロックを残すことができるため、これは合理的です。

注: このソリューションは、それほど大きな画像ではない場合に適しています... HD 画像を使用している場合はお知らせください。

于 2011-01-17T14:30:00.913 に答える
0
using(selectedImg = new Bitmap((Stream)selected))

それでいいの?

于 2011-04-11T21:59:24.807 に答える