亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

c#并行任務多種優化方案分享(異步委托)

2020-01-24 02:57:47
字體:
來源:轉載
供稿:網友

遇到一個多線程任務優化的問題,現在解決了,分享如下。

假設有四個任務:

任務1:登陸驗證(CheckUser)

任務2:驗證成功后從Web服務獲取數據(GetDataFromWeb)

任務3:驗證成功后從數據庫獲取數據(GetDatFromDb)

任務4:使用2、3的數據執行一個方法 (StartProcess)

一個比較笨的方法(本人最開始的方法,記為方法1)是直接開啟一個線程,按照順序依次執行四個任務:

復制代碼 代碼如下:

new Thread(delegate
                {
                    CheckUser();
                    GetDatFromDb();//從數據庫獲取數據
                    GetDataFromWeb();//web服務獲取數據
                    StartProcess();//執行4
                }).Start();

但是仔細分析需求我們會發現,任務2和任務3并沒有先后區別,事實上兩者并無關聯,只不過任務4的執行需要任務2和3都已完成作為條件,所以我們可以再開兩個線程用于執行任務2和任務3,當兩者都執行完畢之后,執行任務4。

在這里使用了兩個全局變量用于表示任務2和任務3的狀態。用三個線程分別執行任務2、3、4,其中任務4一直在循環監聽全局變量的狀態,確保在2、3都執行完畢后才執行。

這記為方法2:

復制代碼 代碼如下:

private static volatile bool _m2;//任務2的標志位
 private static volatile bool _m3;//任務3的標志位
 private static void Main(string[] args)
        {
            new Thread(delegate
                {
                    CheckUser();
                    new Thread(delegate
                        {
                             GetDatFromDb();//從數據庫獲取數據
                             _m2 = true;//標志位置為true
                        }).Start();
                    new Thread(delegate
                        {
                            GetDataFromWeb();//web服務獲取數據
                            _m3 = true;//標志位置為true
                        }).Start();
                    new Thread(delegate
                        {
                            while (!(_m3 && _m2))//判斷任務2和3是否已執行完畢
                            {
                                Thread.Sleep(100);
                            }
                            StartProcess();//執行任務4
                            _m2 = true;
                        }).Start();
                }).Start();
          }

以上代碼基本上已經可以達到預期目標了,但是由于借助了兩個全局變量,盡管在這里不會涉及到同步沖突的問題,但總覺得很不放心,而且當我們需要做擴展的時候,比方說在執行任務4之前,我們還需要加載文件內的數據(GetDataFromFile),那我們必須再添加一個全局標志位,顯得有點麻煩。

事實上,Thread類本身已經擁有對這種情況的完美解決方案――join。

復制代碼 代碼如下:

Thread.Join 方法
在繼續執行標準的 COM 和 SendMessage 消息泵處理期間,阻塞調用線程,直到某個線程終止為止。

簡單來說,join就是個阻塞方法,在線程1內創建線程2,調用線程2的Join方法,那么線程1將會被阻塞,直到線程2執行完畢。運用到上面的例子就是,在任務4內創建任務2和任務3的線程,調用任務2和任務3的線程的Join方法使任務4阻塞,直到任務2和任務3執行完畢,才繼續執行任務4。這記為方法3,代碼如下

復制代碼 代碼如下:

private static void Main(string[] args)
        {
            new Thread(delegate
                {
                    CheckUser();
                    new Thread(delegate
                        {
                            Thread task2 = new Thread(delegate
                                {
                                    GetDatFromDb(); //從數據庫獲取數據
                                });
                            Thread task3 = new Thread(delegate
                                {
                                    GetDataFromWeb(); //web服務獲取數據
                                });
                            task2.Start();
                            task3.Start();
                            task2.Join();//任務2阻塞
                            task3.Join();//任務3阻塞
                            StartProcess(); //執行任務4
                        }).Start();
                }).Start();
        }


這樣便不需要任何標志位了。這是最理想的解決方案。

另外還有一種解決方案,使用EventWaitHandle

復制代碼 代碼如下:

EventWaitHandle 類允許線程通過發出信號和等待信號來互相通信。事件等待句柄(簡稱事件)就是可以通過發出相應的信號來釋放一個或多個等待線程的等待句柄。信號發出后,可以用手動或自動方式重置事件等待句柄

簡單來說,就是方法2的進階版,使用EventWaitHandle控制狀態,而不再使用While循環監聽,但這里仍舊需要兩個全局的EventWaitHandle對象。該方法記為方法4,代碼如下

復制代碼 代碼如下:

private static EventWaitHandle eventWait1 = new EventWaitHandle(false, EventResetMode.AutoReset);//初始化狀態false;
        private static EventWaitHandle eventWait2 = new EventWaitHandle(false, EventResetMode.AutoReset);//初始化狀態false;
        private static void Main(string[] args)
        {
            new Thread(delegate
                {
                    CheckUser();
                     new Thread(delegate
                    {
                        GetDatFromDb(); //從數據庫獲取數據
                        eventWait1.Set(); //標志位置為true
                    }).Start();
                   new Thread(delegate
                    {
                        GetDataFromWeb(); //web服務獲取數據
                        eventWait2.Set(); //標志位置為true
                    }).Start();
                    new Thread(delegate
                        {
                            eventWait1.WaitOne();//任務2阻塞,等待
                            eventWait2.WaitOne();//任務3阻塞,等待
                            StartProcess(); //執行任務4
                        }).Start();
                }).Start();
        }

上述三個優化方案,其實核心思想都是一樣的,都是通過開啟3個線程分別執行2、3、4任務,其中任務4被阻塞(while循環、eventWait.WaitOne,thread.join),當阻塞解除后,繼續執行任務4。也就是說,任務4,其實是一直在等待任務2和任務3的完成。那么,是否有辦法讓任務2和任務3主動通知任務4呢?即,任務2和任務3完成后,主動執行任務4。

方法當然有:異步委托+回調函數

復制代碼 代碼如下:

private static object obj = new object();
        private static volatile bool _m2;//任務2的標志位
        private static volatile bool _m3;//任務3的標志位

        private static void Main(string[] args)
        {
            CheckUser(); //第一步 驗證用戶
            Action step2 = delegate
            {
                GetDatFromDb(); //從數據庫獲取數據
                _m2 = true; //標志位置為true
            };
            Action step3 = delegate
            {
                GetDataFromWeb(); //web服務獲取數據
                _m3 = true; //標志位置為true
            };

            step2.BeginInvoke(delegate
            {
                if (_m2 && _m3) //通過標志位判斷2 3是否都已完成
                {
                    lock (obj)//加鎖
                    {
                        _m2 = false;
                        if (_m3)//二重驗證 防止兩者同時進入
                            StartProcess(); //執行4
                    }
                }
            }, null);
            step3.BeginInvoke(delegate
            {
                if (_m2 && _m3) //通過標志位判斷2 3是否都已完成
                {
                    lock (obj)
                    {
                        _m3 = false;
                        if (_m2)
                            StartProcess(); //執行4
                    }
                }
            }, null);
        }

講解下代碼。首先以委托的方式創建了任務2和任務3的委托對象step2和step3。執行這兩個委托的異步調用方法BegInvoke。執行BegInvoke,會創建一個新的線程來執行step2和step3的方法,同時,在執行BeginInvoke的時候還指定了一個回調函數

復制代碼 代碼如下:

delegate
            {
                if (_m2 && _m3) //通過標志位判斷2 3是否都已完成
                {
                    lock (obj)
                    {
                        _m3 = false;
                        if (_m2)
                            StartProcess(); //執行4
                    }
                }
            }

這個函數會在step2和step3的線程執行完畢后被調用。在這里,我再次使用了標志位來判斷step2和step3是否已經運行完成,同時,為了防止一種特殊情:“step2和step3所執行的時間幾乎相等,他們會同時通過if(_m2&&_m3)判斷,進而執行兩次StartProcess” 在這里加了lock鎖,并且在lock鎖內將標志位重置+二重判斷(這里可以參考單例模式的雙重鎖定原理),確保StarProcess只會執行一次。

如此這般,一個主動通知模式的并行任務便實現了,不過,這種實現方法相較于方法2,實在太過麻煩,尤其在與并發處理方面,個人感覺實用性不太高。

另外,還可以使用觀察者模式實現異步委托+回調函數的效果。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
色一区av在线| 91久久久久久久一区二区| 97精品国产97久久久久久免费| 欧美日韩中文字幕| 亚洲美女av电影| 亚洲自拍偷拍视频| 久久伊人91精品综合网站| 国产精品r级在线| 欧美国产精品日韩| 国产日韩亚洲欧美| 亚洲国产高清福利视频| 国产精品久久一| 欧美亚洲在线观看| 91欧美精品成人综合在线观看| 欧洲精品在线视频| 中文字幕日韩欧美在线| 精品久久中文字幕久久av| 91在线免费视频| 久久伊人91精品综合网站| 久久久久久久久久久av| 国产a级全部精品| 国产一区二区精品丝袜| 欧美华人在线视频| 亚洲大胆人体在线| 欧美电影免费观看高清完整| 一区二区欧美久久| 91深夜福利视频| 国产网站欧美日韩免费精品在线观看| 91tv亚洲精品香蕉国产一区7ujn| 日韩免费看的电影电视剧大全| 亚洲激情视频网| 92国产精品久久久久首页| 久久久久久91香蕉国产| 亚洲va欧美va在线观看| 成人免费视频xnxx.com| 亚洲精品视频网上网址在线观看| 亚洲日本中文字幕免费在线不卡| 久久久国产影院| 日韩黄色高清视频| 亚洲第一精品电影| 久久精品夜夜夜夜夜久久| 97久久精品国产| 国产精品十八以下禁看| 久久夜精品va视频免费观看| 欧美日韩激情视频8区| 91国内免费在线视频| 久久精品视频99| 国产欧美日韩精品丝袜高跟鞋| 日本伊人精品一区二区三区介绍| 91成人国产在线观看| 全球成人中文在线| 动漫精品一区二区| 成人美女免费网站视频| 日韩精品极品在线观看播放免费视频| 久久国产精品99国产精| 久久亚洲精品中文字幕冲田杏梨| 欧美巨猛xxxx猛交黑人97人| 欧美在线xxx| 最近2019年好看中文字幕视频| 中文欧美日本在线资源| 亚洲欧美日韩另类| 精品精品国产国产自在线| 亚洲国产精品网站| 亚洲激情在线观看视频免费| 精品中文字幕乱| 日韩在线观看av| 疯狂做受xxxx高潮欧美日本| 欧美乱妇40p| 日本久久久久久久久久久| 久久在线免费视频| 精品中文字幕久久久久久| 浅井舞香一区二区| 欧美一级淫片播放口| 欧美丰满少妇xxxx| 国产一区二区三区在线免费观看| 国产成人精品一区二区在线| 97国产真实伦对白精彩视频8| 亚洲精品电影在线| 久久在精品线影院精品国产| 成人激情在线播放| 91精品久久久久久久| 日韩精品高清视频| 97视频在线观看播放| 国产一级揄自揄精品视频| 亚洲精品美女久久久| 91亚洲国产成人精品性色| 精品欧美激情精品一区| 欧美日韩在线看| 亚洲精品免费av| 日韩欧美在线国产| 亚洲日韩中文字幕| 午夜精品久久久久久久99热| 亚洲第一区中文99精品| 韩剧1988在线观看免费完整版| 欧美黑人巨大xxx极品| 91精品国产综合久久香蕉的用户体验| 欧美多人爱爱视频网站| 久久久久久国产精品三级玉女聊斋| 亚洲欧美一区二区精品久久久| 日韩免费av一区二区| 欧美日韩一区二区免费在线观看| 高清欧美一区二区三区| 中文字幕国产精品久久| 日韩毛片中文字幕| 伊人久久久久久久久久| 久久影视三级福利片| 日本aⅴ大伊香蕉精品视频| 国产精品99蜜臀久久不卡二区| 久久久久久久久网站| 国产成人a亚洲精品| 国产精品色午夜在线观看| 亚洲精品一区二三区不卡| 欧美一级在线亚洲天堂| 国产福利精品视频| 国产精品羞羞答答| 久久777国产线看观看精品| 欧美老女人在线视频| 久久精品国产成人精品| 97热在线精品视频在线观看| 欧美极品少妇xxxxⅹ喷水| 国产91免费看片| 中文字幕日本精品| 日韩在线视频线视频免费网站| 亚洲欧洲中文天堂| 日韩av黄色在线观看| 中文字幕国产亚洲2019| 国产福利精品在线| 亚洲视频在线观看网站| 亚洲视频专区在线| 欧美夜福利tv在线| 欧美亚洲一区在线| 97免费视频在线播放| 欧美日韩午夜视频在线观看| 国产日韩在线精品av| 国产97在线视频| 国产精品视频区1| 免费不卡在线观看av| 亚洲视频在线免费看| 色先锋久久影院av| 久久久久在线观看| 国产一区二区三区在线观看视频| 亚洲精品一区二区三区婷婷月| 亚洲天堂免费视频| 亚洲xxxx妇黄裸体| 午夜精品久久久久久久99热浪潮| 欧美中文字幕第一页| 国产大片精品免费永久看nba| 国产97在线|日韩| 中文字幕日本欧美| 精品成人国产在线观看男人呻吟| 4388成人网| 色综合视频网站| 成人综合网网址| 国产成人av网| 欧美国产精品日韩| 亚洲午夜色婷婷在线| 亚洲视频综合网| 精品偷拍各种wc美女嘘嘘| 欧美激情免费视频| 亚洲欧美日韩国产中文专区| 欧美日韩另类在线| 国产精品成人国产乱一区| 911国产网站尤物在线观看| 久久成人这里只有精品|