58

你有读写的异步版本(开始/结束函数),但没有删除(我可以告诉你)。这有什么原因吗?没有像读/写那样异步删除的理由吗?

使用线程来模拟异步行为与异步函数不同。很大的不同,确保你得到了感知的并行处理,但它并没有真正防止阻塞,其他线程仍然被阻塞等待文件 i/o 完成。真正的异步函数(开始/结束函数)在系统级别运行,它们将文件 i/o 排队,让应用程序继续,并让应用程序知道它何时准备好继续文件 i/o(允许您在等待文件 i/o 可用时做其他事情)。

4

6 回答 6

44

这会很有用。如果在断开连接的网络共享上删除,DeleteFile 最多可能需要 30 秒。

原因很可能是没有异步删除文件的原生函数。托管 API 通常是非托管 API 的包装器。


现在为什么没有原生的异步文件删除 API?原生异步删除很难在 Windows 上实现。DeleteFile在伪代码中CreateFile加上NtSetInformationFile(Disposition, Delete)plus CloseHandle。没有异步CreateFile(在我看来是 Windows 中的设计错误)。NtSetInformationFile只需在内核中的文件数据结构上设置一个标志。它不能是异步的。实际删除发生在最后一个句柄关闭时。我认为这可能会导致CloseHandle阻塞,这是 Windows 中的另一个设计问题。没有 async CloseHandle

于 2012-05-15T19:25:59.837 回答
15

这个怎么样:

public static class FileExtensions {
   public static Task DeleteAsync(this FileInfo fi) {
      return Task.Factory.StartNew(() => fi.Delete() );
   }
}

然后你可以这样做:

FileInfo fi = new FileInfo(fileName);
await fi.DeleteAsync(); // C# 5
fi.DeleteAsync().Wait(); // C# 4
于 2012-05-15T19:40:36.830 回答
14

该类File不公开异步文件删除方法;但是,通过使用FileStream该类,仍然可以利用提供的 13 个构造函数重载中的特定一个来执行异步文件删除。以下代码将异步删除文件:

using (new FileStream(Path, FileMode.Open, FileAccess.Read, FileShare.None, 1, FileOptions.DeleteOnClose | FileOptions.Asynchronous)) ;

我没有对它进行太多测试,因此您可能需要稍微修改一下用法。FileShare.None(如果在删除期间不应阻止其他线程的文件访问,您可能需要更改为其他内容。)此外,由于此代码不返回 Task 的任何派生,因此使用该Task.Run方法运行它可能是有效的。基本上,它执行的文件删除实际上在 I/O 级别上是异步的,因此在这种情况下将其卸载到线程池应该是可以的。

于 2018-01-06T11:32:31.407 回答
9

如果没有其他东西打开文件,打开FileStreamwithFileOptions.DeleteOnClose将导致 Windows 在流关闭时删除文件。如果您已经打开 aFileStream进行异步读/写,这可能会对您有所帮助,但如果您需要等待删除完成它对您没有帮助(尽管根据 @JoelFan 等待File.Delete完成并不能保证文件实际上已被删除)。

有趣的是,在针对网络共享进行测试时,似乎像这样打开流并且什么都不做比File.Delete

using (new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose)) { }
于 2017-10-12T00:14:25.877 回答
0

我可能是错的,但如果有人试图在跨线程操作上访问同一个文件,则需要阻止文件访问,直到删除操作完成。

于 2012-05-15T19:19:52.577 回答
-5

也许是因为您自己也可以轻松地做到这一点?

var t = Task.Factory.StartNew(() => File.Delete("file.txt"));
// ...
t.Wait();
于 2012-05-15T19:39:03.720 回答