2

我有以下代码来读取文件

StreamReader str = new StreamReader(File.Open(fileName, FileMode.Open, FileAccess.Read));
string fichier = str.ReadToEnd();
str.Close();

这是 asp.net 网络服务的一部分,并且已经在生产中运行了一年。现在随着服务器负载的增加,客户开始收到“文件已在使用”错误。该文件正在从此代码中读取,并且永远不会从应用程序中写入。

我清楚地看到的一个问题是我们没有缓存文件的内容以供将来使用。我们会这样做。但我需要了解我们为什么以及如何遇到这个问题。

是因为多个线程试图读取文件吗?我读到 StreamReader 不是线程安全的,但是当我在读取模式下打开文件时为什么会出现问题?

4

2 回答 2

3

您需要在允许读取访问权限的情况下打开文件。使用此重载File.Open来指定文件共享模式。您可以使用FileShare.Read允许对该文件进行读取访问。

另一种可能的解决方案是在类的静态构造函数中将此文件加载到内存中,然后将内容存储在静态只读变量中。由于静态构造函数保证只运行一次并且是线程安全的,因此您无需执行任何特殊操作即可使其工作。

如果你从不改变内存中的内容,你甚至不需要在访问数据时加锁。如果您确实更改了内容,则每次要更改此数据时都需要先克隆此数据,但是再一次,您不需要锁定克隆操作,因为您的实际原始数据永远不会改变。

例如:

public static class FileData
{
    private static readonly string s_sFileData;

    static FileData ()
    {
        s_sFileData = ...; // read file data here using your code
    }

    public static string Contents
    {
        get
        {
            return ( string.Copy ( s_sFileData ) );
        }
    }
}

这会封装您的数据并为您提供对其的只读访问权限。

仅当您的代码可能修改文件内容时才需要String.Copy()- 这只是强制创建新字符串实例以保护原始字符串的预防措施。由于string它是不可变的,因此只有在您的代码使用字符串指针时才需要这样做 - 我只添加了这一点,因为上周我在自己的代码中遇到了一个类似变量的问题,当时我使用了指向缓存数据的指针。:)

于 2012-11-01T02:29:23.610 回答
1

FileMode 仅控制您可以执行的操作(读/写)。

对文件的共享访问在操作系统级别处理,您可以使用 FileShare(第 3 个参数)请求行为,请参阅doc

于 2012-11-01T02:31:00.943 回答