是“sequential"使用System.IO.File辅助方法的文件I/O是安全的

本文关键字:方法 文件 安全 File sequential quot System 使用 IO | 更新日期: 2023-09-27 18:11:34

我刚刚看到这个问题:在c#中对File类使用静态方法安全吗?总而言之,OP有一个IOException,因为文件在这个ASP中使用。. NET代码片段:

var text= File.ReadAllText("path-to-file.txt");
// Do something with text
File.WriteAllText("path-to-file.txt");

我的第一个想法是这是一个简单的并发访问问题,因为多个ASP。. NET重叠请求。将I/O集中到一个同步的线程安全类中(或者删除文件以支持其他东西)是我想解决的问题。我看了两个答案,当我要给其中一个投票的时候,我看到了那些用户是谁,我想什么h*,然后停了下来。

我将引用它们(然后请参考原始答案以获得更多上下文)。

对于OP段落:

我猜文件读取操作有时在写操作发生之前没有关闭文件[…]

答案是:

正确的。文件系统不支持原子更新[…]使用FileStream没有帮助[…]文件里面没有魔法。它只是使用了FileStream包装为您的方便。

然而,我没有看到原子操作(读+随后的写)和并行(因为部分重叠的多线程请求)的任何期望可能导致并发访问。即使是原子 I/O操作(读+写)也会有完全相同的问题。OK, FileStream 可能是异步的,但File.ReadAllText()File.WriteAllText()不是这样使用的。

另一个答案让我更加困惑,它说:

尽管根据文档,文件句柄保证被此方法关闭,即使引发异常,关闭的时间也不能保证在方法返回之前发生:关闭可以异步完成。

什么?MSDN说方法将打开,读取和关闭文件(也在例外情况下)。这种方法是否可能异步关闭文件?OS会延迟CloseHandle()吗?在哪些情况下?为什么?

总之:这只是一个误解还是CloseHandle()是异步的?我错过了一些非常重要的东西?

是“sequential"使用System.IO.File辅助方法的文件I/O是安全的

如果你看一下CloseHandle文档,它说明每个打开句柄的方法都有一个应该如何关闭的描述:

创建这些对象的函数的文档指示CloseHandle应该在完成时使用对象,以及之后对该对象的挂起操作会发生什么手柄关闭了。通常,CloseHandle会使指定的对象句柄,递减对象的句柄计数,并且执行对象保留检查。对象的最后一个句柄之后关闭,对象将从系统中删除。

当你看CreateFile文档时,它是这样说的:

返回的对象句柄完成应用程序时创建文件时,使用CloseHandle函数关闭句柄。这不是只释放系统资源,但可以对事物产生更广泛的影响例如共享文件或设备以及将数据提交到磁盘。

我发现CloseHandle会导致底层句柄被关闭,同时异步保留文件以进行额外检查,这是很奇怪的。这将削弱操作系统对调用者的许多保证,并将成为许多bug的来源。

问题中的前两个引号不应该是相关的。当File.*完成或关闭FileStream时,文件将立即解锁。从来没有所谓的"徘徊"。如果有的话,你不可能在不重新启动的情况下安全地访问同一个文件。

May answer假定问题中的代码正在并行运行多次。如果不是,那么该代码显然是安全的。

然而,我没有看到任何原子操作的期望…即使是原子I/O操作(读+写)也会有完全相同的问题。

这是真的。我不知道为什么我在我的回答中做出了这样的陈述(尽管这是正确的)。只是不相关)。

关闭的时间不能保证在方法返回之前发生:关闭可以异步完成。

我不知道他为什么这么说,因为在我能想到的任何情况下这都是不正确的。关闭句柄会立即生效。


我认为你对形势的理解是完全准确的。显然,我们的答案不清楚,而且有点误导人……不好意思