.net 为什么不是';net中不存在异步文件删除吗?

.net 为什么不是';net中不存在异步文件删除吗?,.net,file-io,asynchronous,.net,File Io,Asynchronous,您有读写(begin/end函数)的异步版本,但没有delete(我可以说)。这有什么原因吗?异步删除难道没有读/写那么多理由吗 使用线程模拟异步行为与异步函数不同。大的不同,当然你可以感觉到并行处理,但这并不能真正防止阻塞,其他线程仍然被阻塞,等待文件i/o完成。真正的异步函数(开始/结束函数)在系统级运行,它们将文件i/o排队,让应用程序继续运行,并让应用程序知道何时可以继续进行文件i/o(允许您在等待文件i/o可用时执行其他操作)。我可能错了,但是,如果有人试图在跨线程操作中访问同一文件,

您有读写(begin/end函数)的异步版本,但没有delete(我可以说)。这有什么原因吗?异步删除难道没有读/写那么多理由吗


使用线程模拟异步行为与异步函数不同。大的不同,当然你可以感觉到并行处理,但这并不能真正防止阻塞,其他线程仍然被阻塞,等待文件i/o完成。真正的异步函数(开始/结束函数)在系统级运行,它们将文件i/o排队,让应用程序继续运行,并让应用程序知道何时可以继续进行文件i/o(允许您在等待文件i/o可用时执行其他操作)。

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

这将非常有用。如果在断开连接的网络共享上删除,DeleteFile可能需要30秒

原因可能是没有本机函数来异步删除文件。托管API通常是围绕非托管API的包装器



现在为什么没有本机异步文件删除API?本机异步删除很难在Windows上实现
DeleteFile
在pseudocode
CreateFile
plus
NtSetInformationFile(处置,删除)
plus
CloseHandle
。没有异步
CreateFile
(在我看来,这是Windows中的一个设计缺陷)
NtSetInformationFile
只是在内核中的文件数据结构上设置一个标志。它不可能是异步的。当最后一个句柄关闭时,会发生实际的删除。我认为这可能会造成
CloseHandle
阻塞,这是Windows中的另一个设计问题。没有异步的
CloseHandle

也许是因为你自己也可以轻松地完成它

var t = Task.Factory.StartNew(() => File.Delete("file.txt"));
// ...
t.Wait();
这个怎么样:

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

如果文件没有打开,则使用
FileOptions.DeleteOnClose打开
FileStream
,将导致Windows在流关闭时删除该文件。如果您已经打开一个
FileStream
进行异步读/写,这可能会对您有所帮助,但是如果您需要等待删除完成,这对您没有帮助(尽管根据@JoelFan waiting to
File.Delete
to finish并不保证文件实际上已被删除)

有趣的是,在对网络共享进行测试时,似乎打开流本身并对其不做任何操作要比
文件快得多(~40%)。删除

using (new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose)) { }

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

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

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

也许没有必要?要求操作系统以任何方式删除文件需要多长时间?为什么需要删除异步文件?您可以在后台工作程序中执行此操作。@aepheus如果担心线程太多,可以使用线程池。复制、移动和许多其他文件操作也可以使用线程池。我猜微软选择了两个最重要的优先事项,这也是我的选择。这对微软来说是个问题,但不是这样。@ChrisO需要很长、很长、很长的时间。认真地总是假设IO很慢。代码是如何工作的,比如说,一个通过128kbps线路进行网络挂载的文件系统?哈哈,我们同时回答了这个问题。现在他们有两种方法。这基本上是创建一个新线程并运行同步删除。那不是我要找的。真正的异步函数不是使用线程,而是使用本机函数。如果您使用线程,您仍在阻止该线程等待文件i/o,如果您使用异步函数,则不会。@aepheus您所描述的是“重叠”i/o。我不确定为什么没有接受
overlapped
结构的变体,但.NET包装了这些函数,因此没有提供您所要求的内容。顺便说一句,上面的代码不一定会创建一个新线程——它将使用线程池,不会用太多的线程“轰炸”操作系统。您是否确实测量并发现基于任务的方法将是一个性能问题?将工作卸载到另一个线程与异步不同。异步的全部意义在于,在该操作完成时,不会阻止任何工作和线程。如果您等待,这将释放您的UI,但这不是真正的异步,不管异步如何,文件锁定不会仍然发生吗?异步文件i/o基本上只允许您在操作系统为您准备好文件资源时不阻塞,然后让您知道它何时准备好。同样,异步文件i/o只是线程的一个很好的包装,而不是真正的异步文件i/o。异步的主要原因是不阻塞线程(例如,在服务1000个并发请求的web服务器中)。这没有帮助。@usr将文件删除操作委托给异步任务将是异步的,因为即使文件删除操作尚未完成,也可以将响应发送到客户端。即使操作是blo,这也是异步的