【问题标题】:Issues with StreamReader, ThreadSafety and Read ModeStreamReader、ThreadSafety 和读取模式的问题
【发布时间】:2012-11-01 10:42:14
【问题描述】:

我有以下代码来读取文件

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

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

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

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

【问题讨论】:

    标签: c# thread-safety streamreader


    【解决方案1】:

    您需要在允许读取访问权限的情况下打开文件。使用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 是不可变的,因此仅当您的代码使用字符串指针时才需要这样做 - 我只添加了这一点,因为上周我在自己的代码中遇到了一个类似变量的问题,当时我使用了指向缓存数据的指针。 :)

    【讨论】:

      【解决方案2】:

      FileMode 只控制你可以做什么(读/写)。

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

      【讨论】:

        猜你喜欢
        • 2016-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-07
        • 1970-01-01
        相关资源
        最近更新 更多