C# StreamReader、线程安全和读取模式问题

C# StreamReader、线程安全和读取模式问题,c#,thread-safety,streamreader,C#,Thread Safety,Streamreader,我有以下代码来读取文件 StreamReader str = new StreamReader(File.Open(fileName, FileMode.Open, FileAccess.Read)); string fichier = str.ReadToEnd(); str.Close(); 这是asp.net Web服务的一部分,已经在生产中正常工作了一年。现在,随着服务器上负载的增加,客户已开始获取已在使用的文件错误。该文件正在从此代码读取,并且从未从应用程序写入 我清楚地看到的一个问

我有以下代码来读取文件

StreamReader str = new StreamReader(File.Open(fileName, FileMode.Open, FileAccess.Read));
string fichier = str.ReadToEnd();
str.Close();
这是asp.net Web服务的一部分,已经在生产中正常工作了一年。现在,随着服务器上负载的增加,客户已开始获取已在使用的文件错误。该文件正在从此代码读取,并且从未从应用程序写入

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


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

您需要在允许读取访问的情况下打开文件。使用的此重载指定文件共享模式。您可以使用允许对此文件进行读取访问

另一种可能的解决方案是将该文件加载到类的静态构造函数中的内存中一次,然后将内容存储在静态只读变量中。因为静态构造函数保证只运行一次并且是线程安全的,所以不需要做任何特殊的事情来让它工作

如果从不更改内存中的内容,那么在访问数据时甚至不需要锁定。如果确实更改了内容,则每次要更改时都需要首先克隆此数据,但由于实际原始数据从未更改,因此克隆操作不需要锁定

例如:

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实例来保护原始字符串。由于字符串是不可变的,所以只有在代码使用字符串指针时才需要此项。我之所以添加此项,是因为上周我在自己的代码中遇到了一个类似变量的问题,当时我使用了指向缓存数据的指针

您需要以允许的读取权限打开文件。使用的此重载指定文件共享模式。您可以使用允许对此文件进行读取访问

另一种可能的解决方案是将该文件加载到类的静态构造函数中的内存中一次,然后将内容存储在静态只读变量中。因为静态构造函数保证只运行一次并且是线程安全的,所以不需要做任何特殊的事情来让它工作

如果从不更改内存中的内容,那么在访问数据时甚至不需要锁定。如果确实更改了内容,则每次要更改时都需要首先克隆此数据,但由于实际原始数据从未更改,因此克隆操作不需要锁定

例如:

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实例来保护原始字符串。由于字符串是不可变的,所以只有在代码使用字符串指针时才需要此项。我之所以添加此项,是因为上周我在自己的代码中遇到了一个类似变量的问题,当时我使用了指向缓存数据的指针

文件模式仅控制您可以执行的读/写操作


对文件的共享访问是在操作系统级别处理的,您可以使用FileShare 3rd param请求行为,请参见

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

对文件的共享访问是在操作系统级别处理的,您可以使用FileShare 3rd param请求行为,请参阅