从单个文件读取的多个请求(“由另一个进程使用”)

时间:2013-12-16 21:38:58

标签: c# asp.net iis-7 .net-2.0 httphandler

我在这里有一个问题,我希望一些超级专家能够解释。我有一个小的HttpHandler。它从查询字符串中获取文件ID,找到相应的文档路径(来自数据库),并在响应中返回文件内容。

相关代码如下所示:

context.Response.Clear();
context.Response.AddHeader("content-disposition", "attachment;filename=" + file.DisplayName);
context.Response.AddHeader("content-type", mimetype);

string path = context.Server.MapPath(DocumentUploadPath + "/" + file.FileName);

using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read))
{
    byte[] buffer = new byte[32768];
    int bytesRead = 0;

    while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
    {
        context.Response.OutputStream.Write(buffer, 0, bytesRead);
    }
}
context.Response.OutputStream.Flush();

今天检查了我们的错误日志后,我们注意到我们正在按照以下方式获取一些IoExceptions:

  

该进程无法访问文件' file_path_here'因为它是   被另一个进程使用。

为了测试,我设置了一个简单的Parallel.For循环来尝试访问该文件。果然,错误是非常可重复的。它看起来像这样:

static void Main(string[] args)
{
    Parallel.For(0, 1000, ctr =>
    {
        GetFile();
    });
}

static void GetFile()
{
    string fileUrl = "url_to_file.ashx?Id=blah";

    HttpWebRequest request = WebRequest.Create(fileUrl) as HttpWebRequest;

    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

    string responseText = "";

    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
    {
        responseText = reader.ReadToEnd();
    }

    response.Close();
    Console.WriteLine(response.StatusDescription);
}

我已修改处理程序代码以便在遇到该异常时重试,因此问题本身得到了缓解,但这引出了我的一般性问题:

我的服务器如何能够发送数千个index.html的并发副本没问题,但在尝试此操作时会中断(假设没有缓存)?服务器是否为我处理重试,或者它是否能以某种方式同时读取index.html?

2 个答案:

答案 0 :(得分:5)

我认为,如果您添加FileShare.Read,它将解决您的问题

请参阅解释:http://msdn.microsoft.com/en-us/library/system.io.fileshare(v=vs.110).aspx

  

此枚举的典型用法是定义两个进程是否可以同时从同一文件读取。例如,如果打开文件并指定了“读取”,则其他用户可以打开文件进行读取,但不能写入。

using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
   .....
}

答案 1 :(得分:1)

C#" FileStream"构造函数允许您指定" FileShare.Read":

http://msdn.microsoft.com/en-us/library/system.io.fileshare%28v=VS.90%29.aspx

FileStream fs = 
   new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.Read);

我相信" Open"方法: