我的程式需要執行一系列請求。為了性能,我決定使用ActionBlock并并行執行其中的大部分。此外,該應用程式使用一個靜態類進行日志記錄,該類既寫入控制臺又寫入檔案。問題是,即使我SemaphoreSlim在記錄器中添加了一個,但操作塊使用的不同執行緒似乎并不尊重它,并且每隔一段時間我就會在嘗試訪問正在使用的日志檔案時遇到例外。如何正確同步動作塊的動作?這是我的代碼的簡化版本:
private static async Task DoStuffWithThings(List<string> things)
{
var blockOptions = new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = 50
};
var workerBlock = new ActionBlock<string>(DoStuff, blockOptions);
foreach (var t in things)
{
workerBlock.Post(t);
}
workerBlock.Complete();
await workerBlock.Completion;
}
private static void DoStuff(string str)
{
LogMgr.Log($"Doing something with '{str}'...");
DoSomeLongRequest(str);
LogMgr.Log($"First part done. Doing something else with '{str}'...");
DoAnotherLongRequest(str);
LogMgr.Log($"Finished with '{str}'.");
}
這就是記錄器的樣子:
public static class LogMgr
{
private static readonly SemaphoreSlim semaphore = new SemaphoreSlim(1);
public static void Log(string msg)
{
semaphore.Wait(1);
var sw = new StreamWriter($"log.txt", true);
sw.WriteLine(msg);
sw.Close();
semaphore.Release();
}
}
有人可以幫我理解為什么SemaphoreSlim不阻止不同的執行緒同時訪問檔案嗎?
uj5u.com熱心網友回復:
您為等待提供了 1 毫秒的超時時間,因此如果操作花費的時間超過 1 毫秒,您只需讓另一個執行緒進入您的關鍵部分以同時完成作業。
要么不提供任何超時,要么查看 的回傳值,Wait看看你是否真的被授予了鎖,如果是真的,只做有問題的作業。
雖然不是你的錯誤的原因,但你也應該使用 try/finally 來確保如果你確實取出了鎖,你總是呼叫Release,即使發生錯誤,否則寫入這個檔案的例外會讓鎖永遠持有。您應該放入StreamWriterausing以確保在發生錯誤時也將其處理掉(或者更好的是,使用它File.AppendLine來完全避免問題)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/520358.html
標籤:C#多线程同步
