是"顺序"文件I / O与System.IO.File帮助方法安全吗?

时间:2015-09-07 07:52:04

标签: c# .net io

我刚看到这个问题:Is it safe to use static methods on File class in C#?。总结一下,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操作(读取+写入)也会出现完全相同的问题。确定FileStream 可能是异步的,但不是File.ReadAllText()File.WriteAllText()使用它的方式。

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

  

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

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

简而言之:它只是一种误解还是CloseHandle()是异步的?我错过了非常重要的内容?

2 个答案:

答案 0 :(得分:4)

如果查看CloseHandle文档,它会说明打开句柄的每个方法都有关于如何关闭它的说明:

  

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

当您查看CreateFile文档时,就会这样说:

  

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

我会发现,CloseHandle会产生底层句柄被关闭而异步保留文件以进行其他检查,这一点很奇怪。这会削弱操作系统对调用者的许多保证,并且会成为许多错误的来源。

答案 1 :(得分:1)

你问题中的前两个引号不应该是相关的。完成File.*后,或关闭FileStream时,文件会立即解锁。从来没有任何“挥之不去”。如果有,你再也无法安全地访问同一个文件而不重新启动。

可以回答假定问题中的代码并行运行多次。如果没有,该代码显然是安全的。

  

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

这是真的。我不知道为什么我在答案中对此作了陈述(但这是正确的。只是不相关)。

  

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

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

我认为你对这种情况的理解是完全准确的。显然,我们的答案不清楚,有些误导......抱歉。