我的公司推出了我在我們內部網站上託管的每月通訊。我有一個通訊作者的頁面上傳最新版本。一旦作者上傳了最新的時事通訊,他就會發送廣播電子郵件來宣佈新的時事通訊。員工總是檢查新的時事通訊並向作者發送反饋,並進行更正。
一旦作者做出必要的修正(通常發送廣播電子郵件的一個小時內),他再次訪問我的網頁,並替換最新版本與更新的通訊。
緊隨更換(或更新,如果你願意)的通訊的,任何人試圖訪問它得到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