web服务中文件下载的多线程并发问题
本文关键字:多线程 并发 问题 文件下载 服务 web | 更新日期: 2023-09-27 17:54:30
我有一个用于将文件下载到客户机的asmx web服务。我的下载方法如下所示:
[WebMethod]
public byte[] DownloadFile(int id)
{
lock (this)
{
if (id == 0)
{
throw new ArgumentException("Input value is not valid");
}
IGWFileRepository fileRepository = new GWFileRepository();
GWFile file = fileRepository.GetFileById(id);
string path = Server.MapPath(RepositoryDir + "/" + file.DiscName);
BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read));
reader.BaseStream.Position = 0;
byte[] content = reader.ReadBytes(Convert.ToInt32(reader.BaseStream.Length));
reader.Close();
return content;
}
}
我的问题是,当我强调100个用户同时下载时,我得到一个异常:
Exception: System.Web.Services.Protocols.SoapException: System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.IO.IOException: The process cannot access the file 'C:'Subversion'Repository'cb0a27e2-2d23-43b1-a12e-f07fb401cfc9.jpg' because it is being used by another process.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
at System.IO.File.Open(String path, FileMode mode, FileAccess access)
at GrenWebRepository.RepositoryService.DownloadFile(Int32 id) in C:'Subversion'Repository'RepositoryService.asmx.cs:line 62
--- End of inner exception stack trace ---
at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at RepositoryTester.RS.RepositoryService.DownloadFile(Int32 id) in C:'Subversion'Repository'Web References'RS'Reference.cs:line 174
at RepositoryTester.User.DownloadAction() in C:'Subversion'Repository'RepositoryTester'RepositoryTester'User.cs:line 110
(文件名模糊)
有谁知道如何解决并发问题,是我的锁不合适吗?
又快又脏,使用静态私有对象作为锁:
private static object padlock = new object();
public byte[] DownloadFile(int id) {
lock(padlock) {
// code here
}
}
当前锁只存在于创建的类的实例上。为每个请求创建类的新实例。我的解决方案有一个问题,即所有文件都将按顺序读取。如果这会导致性能问题,我只会考虑另一种方法。如果希望并发访问不同的文件,最终需要锁定文件名。这可能需要更多的工作。
我猜在使用FileStream后处理它会有所帮助。
试着把它包含在using块中,像这样:
using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read))
{
....
}
下面的代码将简化您的代码,并且可能解决由于没有处理FileStream
而导致的问题:
string path = Server.MapPath(RepositoryDir + "/" + file.DiscName);
byte[] content = File.ReadAllBytes(path);
File.ReadAllBytes
与FileAccess.Read
和FileShare.Read
打开文件