public class Logger??? {??????????????? private Queue queue;??????? private ManualResetEvent manual;
?????????????? private Thread logThread;??????? /// ??????? /// 指定存儲文件的路徑??????? /// ??????? public static string Path { get; set; }
??????? //私有構造函數,初始化相關對象 使用單例模式??????? private Logger()??????? {??????????? queue = new Queue();??????????? manual = new ManualResetEvent(false);??????????? logThread = new Thread(Process);??????????? logThread.IsBackground = true;??????????? logThread.Start();??????? }??????? private readonly static Logger logger = new Logger();??????? private static Logger GetInstance()??????? {??????????? return logger;??????? }??????? //不斷處理隊列中的任務??????? private void Process()??????? {??????????? while (true)??????????? {??????????????????????????????? manual.WaitOne();
???????????????????????????? manual.Reset();
?????????????????????????????? Thread.Sleep(100);
????????????????????????????? Queue copy;??????????????? lock (queue)??????????????? {??????????????????? copy = new Queue(queue);??????????????????? queue.Clear();??????????????????? foreach (var action in copy)??????????????????????? action();??????????????? } ??????????? }??????? }??????? private void ExcuteAction(string log)??????? {??????????? string date = DateTime.Now.ToString();??????????? string path;??????????? if (!string.IsNullOrEmpty(Path))??????????????? path = Path + "log.txt";??????????? else??????????????? path = "log.txt";??????????? lock(queue)??????????? {???????????????????????????? queue.Enqueue(() => File.AppendAllText(path, log+" : "+date + Environment.NewLine));??????????? }??????????????????????? manual.Set();??????? }
??????????????? /// ??????? /// 將數據寫入文件中??????? /// ??????? /// 要寫入的數據??????? public static void WriteLog(string log)??????? {??????????? // WriteLog 方法只是向隊列中添加任務,執行時間極短,所以使用Task.Run。??????????? Task.Run(() =>??????????? {??????????????? GetInstance().ExcuteAction(log);??????????? });??????? }
}
?兩條線程讀寫同一個對象,兩條線程都lock這個對象?用ManualResetEvent來控制讀數據的線程(Thread(Process))?當寫數據的線程(Task.Run)有數據寫入時開啟讀線程工作?這樣有可能控制并發,但測試幾次,發現幾次數據的順序有誤,但沒有漏主線程和新線程調用第三次后順序沒錯? 開Task線程調用順序完全相反,開始兩次也會有些亂!?。。。。。。。。。。?
7 回答

12345678_0001
TA貢獻1802條經驗 獲得超5個贊
從隊列中取元素的時候不要foreach要出隊.放進去的也時候,操作private Queue queue;對象就好.不要想太多.
人家隊列類都給你做好這些東西了.你不用怪誰.

慕桂英546537
TA貢獻1848條經驗 獲得超10個贊
Queue換成ConcurrentQueue,其他所有互斥量全部拿掉,就當做單線程處理即可。
另while(true)這種做法不好,相當于你就只考慮開始不考慮結束,如果中途需要停止最好是通過通知的方式傳過來。

神不在的星期二
TA貢獻1963條經驗 獲得超6個贊
謝謝指點,我也不喜歡while(true)我就是想試試線程安全和并發,我是業余自學.net的,文化有限,初中畢業,現在人也老了,估計是沒希望從事這行了。開始學的還蠻好的,后面越來越覺得要學的太多

蕪湖不蕪
TA貢獻1796條經驗 獲得超7個贊
@隨機哥丶: .net的學習曲線較java而言平滑一些,當然隨著了解的深入涉及的東西就會越多,這個是沒有辦法的。關于多線程,建議先不要看task和并行,直接學thread及threadpool,幾種信號量。練手也不要以有外部依賴的東西著手(比如你讀寫文件,這個實際會使場景變的更復雜),選用普通的cpu密集型計算更簡單而且也容易驗證些(比如數字的累加)。
- 7 回答
- 0 關注
- 418 瀏覽
添加回答
舉報
0/150
提交
取消