国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

C#線程會合實例

2019-11-14 14:01:55
字體:
來源:轉載
供稿:網友

有這樣一個題目:四個線程t1,t2,t3,t4,向4個文件中寫入數據,要求:t1只能寫入“1”,t2只能寫入“2”,t3只能寫入“3”,t4只能寫入“4”,對4個文件A,B,C,D寫入如下內容:

  • A:123412341234.....
  • B:234123412341....
  • C:341234123412....
  • D:412341234123....

簡單分析一下,對于A文件,t1寫入“1”后,我們希望通知t2來寫“2”,并且t1前往D文件等著去寫“1”,以此類推。

1. 通過等待句柄實現

顯然可以用等待句柄來實現,通知t2來寫“2”相當于在一個等待句柄上調用 Set 方法,等待在D文件上寫“1”相當于在另一等待句柄上調用了 WaitOne 方法,下邊是利用4個 AutoResetEvent 來實現它:

class PRogram{    private static List<StreamWriter> _sws;    private static List<AutoResetEvent> _whs;

private static void Main(string[] args) { var fileNames = new List<string> {"A", "B", "C", "D"}; // 創建或清空文件 fileNames.ForEach(name => { if (!File.Exists(name)) File.Create(name).Close(); else { using (var sw = new StreamWriter(name)) sw.Write(""); } }); _sws = fileNames.Select(File.AppendText).ToList(); // 為每個文件寫入建立一個等待句柄 _whs = fileNames.Select(name => new AutoResetEvent(false)).ToList(); // 創建并啟4個線程執行任務 var threads = new List<Thread> { new Thread(() => Work(1)), new Thread(() => Work(2)), new Thread(() => Work(3)), new Thread(() => Work(4)) }; threads.ForEach(t => t.Start()); // 等待線程結束并關閉 StreamWrite threads.ForEach(t => t.Join()); Console.WriteLine("任務完成!"); _sws.ForEach(sw => sw.Close()); } static void Work(int threadIndex) { var next = threadIndex - 1; // 為讓程序能結束,就打印100次 for (int i = 0; i < 100; i++) { var wh = _whs[next]; var sw = _sws[next]; lock (sw) { sw.Write(threadIndex); } next = (next - 1) < 0 ? 3 : next - 1; WaitHandle.SignalAndWait(wh, _whs[next]); //在wh上發信號,并在下一個等待句柄上等待執行 } }}

上述例子中我們創建了4個線程來分別打印1,2,3,4,并且為每個文件的寫入創建了4個等待句柄來進行信號通信。最后主線程在等待所有線程結束后,關閉文件流。為讓程序能正常結束,在 Work 方法中就只循環寫100次。

以t1(列表中第一個線程)為例,在A文件中打印1后,調用 WaitHandle.SignalAndWait(wh,wh[next]),即在wh上發信號通知可以接著寫入了,并在下一個等待句柄上等待寫入信號。

關于 SinalAndWait 的可以參見 Thread in C# 或者對應的 中文翻譯 。

2. 通過 Barrier 類實現

除了通過等待句柄可以實現題目要求外,同樣可以通過 WaitPulse 來實現。如果是FrameWork 4.0或更高的版本,可以通過 Barrier 類(它是建立在 Wait / Pulse 和自旋鎖基礎上的)更簡單的實現這個題目。

class Program{    private static Barrier _barrier;    private static void Main(string[] args)    {        var fileNames = new List<string> { "A", "B", "C", "D" };        // 創建或清空文件        fileNames.ForEach(name =>        {            if (!File.Exists(name))                File.Create(name).Close();            else            {                using (var sw = new StreamWriter(name))                    sw.Write("");            }        });                // 在_barrier上調用SignalAndWait的線程會被阻塞直到這個方法被調用4次        _barrier = new Barrier(4);        _sws = fileNames.Select(File.AppendText).ToList();        // 創建并啟4個線程執行任務        var threads = new List<Thread> {            new Thread(() => Work(1)), new Thread(() => Work(2)), new Thread(() => Work(3)), new Thread(() => Work(4))        };        threads.ForEach(t => t.Start());        // 等待線程結束并關閉 StreamWrite        threads.ForEach(t => t.Join());        Console.WriteLine("任務完成!");        _sws.ForEach(sw => sw.Close());    }    static void Work(int threadIndex)    {        var next = threadIndex - 1;        for (int i = 0; i < 100; i++)        {            var sw = _sws[next];            lock (sw)            {                sw.Write(threadIndex);            }            _barrier.SignalAndWait();            next = (next - 1) < 0 ? 3 : next - 1;        }    }}

使用了一個 Barrier 類來替代4個等待句柄,線程調用 SignalAndWait 后會阻塞,直到這個方法被調用4次。在這個例子中意味著4個線程總是在同步進行著打印,下圖可以很好的解釋 Barrier 類:

 關于 Barrier 類,可以參見 Thread in C# 或者對應的 中文翻譯 。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 汉源县| 胶州市| 双辽市| 宜兰县| 三河市| 梅河口市| 博野县| 康马县| 武功县| 翼城县| 沭阳县| 荔浦县| 望谟县| 连州市| 安阳县| 阿拉善右旗| 徐水县| 花莲市| 阳新县| 凤山市| 阿鲁科尔沁旗| 哈尔滨市| 澜沧| 永兴县| 于田县| 霍林郭勒市| 石首市| 齐齐哈尔市| 濮阳县| 广饶县| 都昌县| 馆陶县| 营口市| 云林县| 玉山县| 林州市| 德保县| 四川省| 南澳县| 濉溪县| 常德市|