在ASP.NET MVC中将FileShare.ReadWrite与HttpPostedFile一起使用

时间:2019-05-25 18:23:25

标签: c# .net asp.net-mvc stream file-permissions

我正在使用下面的代码将发布的文件保存到服务器,但是该文件正在被连续读取,因此需要使用FileShare.ReadWrite,这样我就不会遇到锁定错误。

 httpRequest.Files[0].SaveAs(filePath);

下面是我的阅读方法,如何用HttpPosted文件完成此操作是性能最佳的正确方法。

using (var fileStream = new FileStream(
                   fileLocation,
                   FileMode.Open,
                   FileAccess.Read,
                   FileShare.ReadWrite))
                {
                    using (var streamReader = new StreamReader(fileStream))
                    {
                        xDocument = XDocument.Parse(streamReader.ReadToEnd());
                    }
                }

这是我最好的选择吗?

 using (var memoryStream = new MemoryStream())
                {
                    httpRequest.Files[0].InputStream.CopyTo(memoryStream);
                    var bytes = memoryStream.ToArray();

                    using (var fs = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
                    {
                        fs.Write(bytes, 0, bytes.Length);
                    }
                }

1 个答案:

答案 0 :(得分:2)

问题:

  • 您想要一个“写:一次,读:很多”锁

假设:

  • 文件很小(平均写入时间为5000毫秒)
  • 没有其他写入或读取操作(只有一个程序具有2个功能)
  • 您读取文件比写入文件要多

解决方案


    using System;
    using System.IO;
    using System.Threading;
    using System.Web.Mvc;

    namespace stackoverflow_56307594.Controllers
    {

        public class HomeController : Controller
        {

            public ActionResult A()
            {
                readFile();
                return View();
            }

            public ActionResult B()
            {
                writeFile();
                return View();
            }


            private static object writeLock = new Object();

            private void readFile()
            {
                while (!Monitor.TryEnter(writeLock, 5000)) ; //wait 5000 ms for the writeLock (serializing access)
                using (var stream = new FileStream("filePath", FileMode.Open, FileAccess.Read, FileShare.Read))
                using (var reader = new StreamReader(stream))
                {
                    // active read
                    // xDocument = XDocument.Parse(streamReader.ReadToEnd());

                }
            }
            private void writeFile()
            {
                lock (writeLock)
                {
                    FileStream stream = null;
                    while (stream == null) //wait for the active read
                    {
                        try
                        {
                            stream = new FileStream("filePath", FileMode.Open, FileAccess.ReadWrite, FileShare.None);
                        }
                        catch (IOException)
                        {
                        // will fail if active read becase FileShare.None   while (stream == null) will  wait
                    }
                }
                    Request.Files[0].InputStream.CopyTo(stream);
                }// unlock
            }

        }
    }

注意:

  1. 我没有测试负载或只是在Web服务器上测试了解决方案
  2. 我只在纸上测试过

enter image description here

参考:

locking - How long will a C# lock wait, and what if the code crashes during the lock? - Stack Overflow

c# - Deleting files in use - Stack Overflow

multithreading - Is there a way to detect if an object is locked? - Stack Overflow

Implementing Singleton in C# | Microsoft Docs

c# - Using the same lock for multiple methods - Stack Overflow

c# - Write-Once, Read-Many Lock - Stack Overflow

c# lock write once read many - Google Search

FileShare Enum (System.IO) | Microsoft Docs