我的公司推出了我在我们内部网站上托管的每月通讯。我有一个通讯作者的页面上传最新版本。一旦作者上传了最新的时事通讯,他就会发送广播电子邮件来宣布新的时事通讯。员工总是检查新的时事通讯并向作者发送反馈,并进行更正。
一旦作者做出必要的修正(通常发送广播电子邮件的一个小时内),他再次访问我的网页,并替换最新版本与更新的通讯。
紧随更换(或更新,如果你愿意)的通讯的,任何人试图访问它得到500 - 内部服务器错误。
维护服务器的IT人员由于权限错误无法删除/重命名/移动文件,因此必须执行许多令人费解的操作来删除文件(并且一旦文件被删除,作者通讯可以重新上传正确的副本,它的工作正常。
我的IT人员和我很确信,问题源于我试图替换文件,而IIS正在积极为用户提供服务(我想到并认为我已经编码发生了)
运行替换的代码如下:
Protected Sub ReplaceLatestNewsletter()
Dim dr As DataRow
Dim sFile As String
Dim mFileLock As Mutex
Try
If Me.Archives.Rows.Count > 0 Then
dr = Me.Archives.Rows(0)
sFile = dr("File").ToString
If dr("Path").ToString.Length > 0 Then
mFileLock = New Mutex(True, "MyMutexToPreventReadsOnOverwrite")
Try
mFileLock.WaitOne()
System.IO.File.Delete(dr("Path").ToString)
Catch ex As Exception
lblErrs.Text = ex.ToString
Finally
mFileLock.ReleaseMutex()
End Try
End If
fuNewsletter.PostedFile.SaveAs(Server.MapPath("~/Newsletter/archives/" & sFile))
End If
Catch ex As Exception
lblErrs.Text = ex.ToString
End Try
dr = Nothing
sFile = Nothing
mFileLock = Nothing
End Sub
我以为Mutex
会照顾这个(虽然经过重新阅读文档,我不知道我实际上可以使用它像我想)。上面的代码其他评论:
Me.Archives
是存储在ViewState
dr("File").ToString
一个DataTable
是文件名(无路径)dr("Path").ToString
是完整的本地机器路径和文件名(即,C:\ APP_ROOT \通讯\档案\ 20120214.pdf')- 的通讯的文件名设置为‘YYYYMMDD.pdf’其中YYYYMMDD是上传的日期(格式)。
在任何情况下,我敢肯定,上面的代码是不建立文件上的独占锁,以使文件可以被安全地覆盖。
最后,我想,以确保发生以下情况:
- 如果IIS现任文件,等到IIS完成服务它。
- 之前IIS可以再次提供服务的文件,该文件确立的排他锁,这样其他进程,线程,用户(等)无法读取或写入文件。
- 删除该文件完全谱写新的文件来替换它或覆盖与新内容的现有文件。
- 删除独占锁以便用户可以再次访问文件。
建议?
此外,我可以使用Mutex
获取Windows文件系统中文件的互斥锁吗?
预先感谢您为您的帮助和建议。
编辑:
,对于产生的通讯链路是基于物理文件名的方式。使用的方法是:
- 获取“存档”目录中的所有PDF文件。对于每个文件:
- 解析公布的从文件名的日期。
- 店日期,文件路径,文件名,并在
DataTable
- 排序
DataTable
按日期(降序)的URL的每个文件在DataRow
。 - 输出第一行作为当前问题。
- 输出所有后续行作为“档案”按年份和月份举办。
UPDATE:
代替不能够在该文件中的所有现有请求已经完成辨别的,我接过仔细看看@贾斯汀的回答(“你的互斥的第一部分将只有在从文件中读取的进程也获得相同的互斥量时才有效果。“)
这导致我在Configure IIS7 to server static content through ASP.NET Runtime和被接受的答案中链接的文章。
为此,我对所有实现New Mutex(True, "MyMutexToPreventReadsOnOverwrite")
的PDF文件实施了一个处理程序,以确保在任何给定时间只有一个线程正在使用PDF进行操作。
谢谢你的回答,@Justin。虽然我没有结束使用您建议的实现,但您的回答指向我一个可接受的解决方案。
我添加了c#标签,因为我可以读取c#并将其翻译回vb.net。随意在c#中发布代码。 – pete 2012-02-21 16:37:04
所有应有的尊重 - 这是愚蠢的。为什么不只是1)上传到“暂存区域”(即*始终*可写入),然后2)复制 - 在“正在使用文件”错误时“重试”? – paulsm4 2012-02-21 16:48:15