利用安全且非獨占的方式,將檔案內容讀取或寫回
在伺服器端操作文字檔案的讀取總是令人擔心,因為是多人多工的環境,一不小心就會造成資源鎖死(死結)。舉例來說,如果你開啟一個文字檔案的方式錯誤,可能會造成其他執行緒 無法在你讀取檔案的當下,跟你一起分享這個檔案的讀取權限,這樣的設計會造成佇列的排隊,而如果被等候的執行緒剛好出了甚麼差錯,這下就是災難的開始了。
如何正確的利用.NET Framework檔案共享的讀取方式,將權限共享給其他的執行緒?
簡單的說,就是放棄寫入權限,並且依循Windows底層的檔案共享讀取機制,將檔案正確的設定共享讀取的權限,以防止咬檔的問題產生。程式碼如下:
using (
System.IO.StreamReader oSR = new System.IO.StreamReader
(
new System.IO.FileStream
(
cFilePathAndName,
System.IO.FileMode.Open,
System.IO.FileAccess.Read,
System.IO.FileShare.ReadWrite
)
))
{
oSR.ReadToEnd();
}
透過這樣的方式,如果有其他的執行緒要一起進行這個文字檔的讀取,是不會產生咬死的狀況喔!很古老的資料了,但是每次要實作總會因為膽戰心驚又要去找一次資料,因此將其記錄在這裡嘍!
用非獨占的方式將檔案回寫
寫入跟讀取的情況又不太一樣了,因為對OS來說,寫入檔案在怎麼神奇,永遠同時間也是只能一個執行緒使用而已,因此如果場景搬到Web上,最好上個lock把執行緒序列化一下會比較安全。
private static System.Object _oLock = new System.Object();
public void WriteUpdate()
{
lock (_oLock)
{
using (System.IO.StreamWriter oSW = new System.IO.StreamWriter(
new System.IO.FileStream
(
path: cFilePathAndName,
mode: System.IO.FileMode.OpenOrCreate,
access: System.IO.FileAccess.Write,
share: System.IO.FileShare.ReadWrite
),
System.Text.Encoding.UTF8
)
)
{
oSW.WriteLine(YourData);
oSW.Flush();
}
}
}
對於寫入的程式碼,這邊針對mode做一下小小的補充,如果你要寫入的速度效能最大化,那麼應該設定成System.IO.FileMode.OpenOrCreate,在多執行緒的情景實際測試下來會比System.IO.FileMode.Create的效能快約3倍以上(1xxms變成3xms)。
然而,有一好沒兩好,如果你這個檔案是要給ASP.NET做快取(Cache)監控用的,那麼System.IO.FileMode.Create會是你的最佳選擇,因為Create會把檔案砍掉重新創造一個新檔案,這會造成SMB的檔案監控馬上觸發,因此依存在這個檔案上的快取會馬上消失。而OpenOrCreate會進行檔案的開啟與修改,這時SMB的檔案監控機制沒有辦法馬上反應,反而要等待10~15秒左右才會觸發(發現這個檔案被異動過),這對網站要求Cache要即時因為修正檔案而反應的效率上,因而大打折扣喔!