原文:[C#] 使用 SpinWait 实作档案存取 Lock 机制
今天在设计档案 Lock 机制的时候,发现了一个好物 SpinWait
可以用,比起 Thread.Sleep()
+ While(true)
更来的方便效能也较佳。
多条执行续存取相同档案时,基本要注意的事情如下:
我读取档案时,允许他人读取不允许写入。我写入档案时,不允许他人读写。这边我设计了一个 FileHandler
来处理这件事情,程式码如下:
public class FileHandler{ public void WriteFileContent(string content) { using (var fs = waitFileForUse(FileAccess.Write, FileShare.None)) { fs.SetLength(0); using (var sw = new StreamWriter(fs, Encoding.UTF8)) { sw.Write(content); } } } public string ReadFileContent() { using (var fs = waitFileForUse(FileAccess.Read, FileShare.Read)) { using (var sr = new StreamReader(fs, Encoding.UTF8)) { return sr.ReadToEnd(); } } } private FileStream waitFileForUse(FileAccess fileAccess, FileShare fileShare) { const int maxRetryMilliseconds = 5 * 1000; string filePath = "note.json"; FileStream fs = null; SpinWait.SpinUntil(() => { try { fs = new FileStream(filePath, FileMode.OpenOrCreate, fileAccess, fileShare); } catch { } return (fs != null); }, maxRetryMilliseconds); if (fs == null) { throw new IOException($"无法开启 {filePath}, 已超过 {maxRetryMilliseconds} ms 重试上限"); } return fs; }}
waitFileForUse
这个 Method 里面我使用了 SpinWait
来去判断档案是否可以存取,并设定 Timeout 秒数避免 Deadlock 的问题发生。