Parallel Programming-實現並行操作的流水線(生產者、消費者)

来源:http://www.cnblogs.com/ldyblogs/archive/2017/11/14/Parallel.html
-Advertisement-
Play Games

Parallel Programming-實現並行操作的流水線(生產者、消費者) ...


本文介紹如何使用C#實現並行執行的流水線(生產者消費者):

1.流水線示意圖

2.實現並行流水線

一、流水線示意圖

 

上圖演示了流水線,action1接收input,然後產生結果保存在buffer1中,action2讀取buffer1中由action1產生的數據,以此類推指導action4完成產生Output。

以上也是典型的生產者消費者模式。

上面的模式如果使用普通常規的串列執行是很簡單的,按部就班按照流程圖一步一步執行即可。如果為了提高效率,想使用並行執行,也就是說生產者和消費者同時並行執行,該怎麼辦麽?

二、實現並行流水線

2.1 代碼

class PiplelineDemo
    {
        private int seed;
        public PiplelineDemo()
        {
            seed = 10;
        }

        public void Action1(BlockingCollection<string> output)
        {
            try
            {
                for (var i = 0; i < seed; i++)
                {
                    output.Add(i.ToString());//initialize data to buffer1
                }
            }
            finally
            {
                output.CompleteAdding();
            }
        }

        public void Action2(BlockingCollection<string> input, BlockingCollection<string> output)
        {
            try
            {
                foreach (var item in input.GetConsumingEnumerable())
                {
                    var itemToInt = int.Parse(item);
                    output.Add((itemToInt * itemToInt).ToString());// add new data to buffer2
                }
            }
            finally
            {
                output.CompleteAdding();
            }
        }

        public void Action3(BlockingCollection<string> input, BlockingCollection<string> output)
        {
            try
            {
                foreach (var item in input.GetConsumingEnumerable())
                {
                    output.Add(item);//set data into buffer3
                }
            }
            finally
            {
                output.CompleteAdding();
            }
        }

        public void Pipeline()
        {
            var buffer1 = new BlockingCollection<string>(seed);
            var buffer2 = new BlockingCollection<string>(seed);
            var buffer3 = new BlockingCollection<string>(seed);
            var taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.None);
            var stage1 = taskFactory.StartNew(() => Action1(buffer1));
            var stage2 = taskFactory.StartNew(() => Action2(buffer1, buffer2));
            var stage3 = taskFactory.StartNew(() => Action3(buffer2, buffer3));

            Task.WaitAll(stage1, stage2, stage3);
            foreach(var item in buffer3.GetConsumingEnumerable())//print data in buffer3
            {
                Console.WriteLine(item);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            new PiplelineDemo().Pipeline();
            Console.Read();
        }
    }

2.2 運行結果

預期列印出了0-9自我相乘的結果。

2.3 代碼解釋

代碼本身的邏輯和本文開始的流程圖是一一對應的。

BlockingCollection<T>是.Net裡面的一個線程安全集合。實現了IProducerConsumerCollection<T>.

  1. Add方法:將元素加入集合
  2. CompleteAdding方法:告訴消費者,在當調用該方法之前的元素處理完之後就不要再等待處理了,可以結束處理了。這個非常重要,一定要執行,所以放在finally中(就算exception也要執行)
  3. GetConsumingEnumberable,給消費者返回一個可以便利的集合

以上動圖由“圖鬥羅”提供

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • HAL(Hypertext Application Language,超文本應用語言)是一種RESTful API的數據格式風格,為RESTful API的設計提供了介面規範,同時也降低了客戶端與服務端介面的耦合度。很多當今流行的RESTful API開發框架,包括Spring REST,也都預設支 ...
  • 1.1 概述 c#程式開發中,資料庫操作無疑是舉足輕重的,資料庫部分的技術點可能占整個c#技術點的1/4。這幾天我一直在研究System.Data.OracleClient.dll反編譯之後的.CS,放棄c#的心都有了,底層代碼不僅全是英文註釋,而且有很多東西看都看不懂,讓我深刻體會封裝的重要性!此 ...
  • 今天是第一次接觸C#,由於長時間的做Java開發,突然轉到C#非常的不自然,但是也有了一些收穫,給大家分享一下 ...
  • "sweetalert": "^1.1.3",記住這個參數,Abp中這個組件只能用這個版本,高於它的message會沒有效果,切記 ...
  • 回到目錄 進行dotnetcore之後,各種對象都是基於DI進行生產的,這就有了對象的生命周期一說,早在autofac里也有相關知識點,這與Microsoft.Extensions.DependencyInjection是完全溫和的,方便大家理解,在講今天的組件化之前,先對DI的三種生命周期進行理解 ...
  • 大致要實現的 效果如下 1,添加Controller(用到的X.PagedList 註意到nuget添加) 2,視圖 另外還有_createTaskPartial,_EditTaskPartial 等,這裡就不貼代碼了 以上。。。 參考http://www.jianshu.com/p/620c20f ...
  • 最近在練習EF的過程中,實現將Linq返回的結果綁定到Combox時出錯。 錯誤提示如下: System.NotSupportedException:“Data binding directly to a store query (DbSet, DbQuery, DbSqlQuery, DbRawS... ...
  • 一,一些相關解釋 Service 在應用服務層也就是application層。應用服務用於將領域(業務)邏輯暴露給展現層。展現層通過傳入DTO(數據傳輸對象)參數來調用應用服務,而應用服務通過領域對象來執行相應的業務邏輯並且將DTO返回給展現層。 也就是這樣避免了應用服務層和展現層的,直接數據交互, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...