StreamReader,ThreadSafety和Read Mode的问题

时间:2012-11-01 02:24:38

标签: c# thread-safety streamreader

我有以下代码来读取文件

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

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

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

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

2 个答案:

答案 0 :(得分:3)

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

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

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

例如:

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是不可变的,所以只有当你的代码使用字符串指针时才需要这个 - 我只添加了这个位,因为我上周在我自己的代码中遇到了类似变量的问题,我使用了指向缓存数据的指针。 :)

答案 1 :(得分:1)

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

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