6

私は奇妙な問題(おそらく私の知識不足です)に悩まされています。問題のあるコードを提示します:

try
{
    f.Delete();
    fTemp.MoveTo(f.FullName);
    Console.WriteLine("INFO: Old file deleted new file moved in > {0}", f.FullName);
}
catch (IOException ex)
{
    Console.WriteLine("ERROR: Output file has IO exception > {0}", f.FullName);
    Environment.ExitCode = 1;
}

f と fTemp は FileInfo オブジェクトです。したがって、f がメディアプレーヤーで再生中のビデオ ファイルであるコードでこれを実行すると、例外がスローされます。それは正常に動作し、期待どおりです。メディアプレーヤーを閉じると、ファイルが削除されます!? 私のアプリケーションは長い間閉鎖されていますが。Visual Studio を閉じても、メディア プレーヤーを閉じるとファイルが削除されます。ある時点でファイルが確実に削除されるように、コールバックがどこかにセットアップされているかのように。望ましくない行動のこのオフコース。しかし、私は正確に何が間違っているのか理解できません...

今のところの結果:

if (!IsFileLocked(f))
{
    try
    {
        f.Delete();
        fTemp.MoveTo(f.FullName);
        Console.WriteLine("INFO: Old file deleted new file moved in > {0}", f.FullName);
    }
    catch (IOException ex)
    {
        Console.WriteLine("ERROR: Output file has IO exception > {0}", f.FullName);
        Environment.ExitCode = 1;

    }

    catch (UnauthorizedAccessException ex)
    {
        Environment.ExitCode = 2;
        Console.WriteLine("ERROR: Output file is locked > {0}", f.FullName);

    }
}
else
{
    Environment.ExitCode = 3;
    Console.WriteLine("ERROR: Couldn't delete file was locked");

}

Delete と MoveTo の間でまだうまくやれることはわかっていますが、とりあえず変更を行います。ショットガン コーディング.....

4

3 に答える 3

3

IOExceptionファイルをすぐに削除したり書き込んだりすることはできないため、を取得しています。ただし、を呼び出すDelete()と、ファイルが削除のために呼び出されているようです。

メディアプレーヤーは、開いている間はファイルの削除を停止しますが、プログラムが実行されているかどうかに関係なく、ファイルを閉じるとファイルは削除対象としてマークされます。したがって、メディアプレーヤーを閉じると、ファイルは削除されます。

ここから取得した次のコードで、ファイルが使用されているかどうかを確認できます。ロックされていないことDeleteCopy条件として、を作成します。そうすれば、問題はありません。

try
{
    if(!IsFileLocked(f))
    {
        f.Delete();
        fTemp.MoveTo(f.FullName);
        Console.WriteLine("INFO: Old file deleted new file moved in > {0}", f.FullName);
    }
}

protected virtual bool IsFileLocked(FileInfo file)
{
    FileStream stream = null;

    try
    {
    stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
    }
    catch (IOException)
    {
    //the file is unavailable because it is:
    //still being written to
    //or being processed by another thread
    //or does not exist (has already been processed)
    return true;
    }
    finally
    {
    if (stream != null)
        stream.Close();
    }

    //file is not locked
    return false;
}
于 2012-08-01T15:01:41.403 に答える
1

Windows SDK から:

DeleteFile 関数は、ファイルを閉じるときに削除するようにマークします。したがって、ファイルの最後のハンドルが閉じられるまで、ファイルの削除は行われません。ファイルを開くための CreateFile への後続の呼び出しは、ERROR_ACCESS_DENIED で失敗します。

于 2012-08-01T15:05:03.260 に答える
0

私が理解している限り、ファイルが削除されるまでプログラムを待機させてから、それを削除して他のファイルを移動する必要があります。

これを行うには、ファイルで開いているハンドルがあるかどうかを確認できますが、これにはアンマネージ コードが必要です。もう 1 つの方法は、この質問の回答のメソッドを使用することです: Is there a way to check if a file is in use?

protected virtual bool IsFileLocked(FileInfo file) 
{ 
    FileStream stream = null; 

    try 
    { 
        stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None); 
    } 
    catch (IOException) 
    { 
        //the file is unavailable because it is: 
        //still being written to 
        //or being processed by another thread 
        //or does not exist (has already been processed) 
        return true; 
    } 
    finally 
    { 
        if (stream != null) 
            stream.Close(); 
    } 

    //file is not locked 
    return false; 
} 

ファイルの削除を開始する前に、

A) ファイルが削除できるまでループする

while(IsFileLocked(f)) { Thread.Sleep(100); }

または B) キャンセル

if (IsFileLocked(f)) { return; }

AまたはBを選択する場合は、要件によって異なります。

于 2012-08-01T15:10:24.517 に答える