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 之间做得更好,但我现在将进行更改,shotgun 编码......

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

据我了解,您希望您的程序等到可以删除文件然后删除它并移动另一个文件。

为此,您可以检查文件上是否打开了句柄,但这需要非托管代码。另一种方法是使用这个问题的答案中的方法:有没有办法检查文件是否正在使用?

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 回答