最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2013年12月27日 15:25:34   作者:  
c#并行任務(wù)多種優(yōu)化方案分享,使用異步委托+回調(diào)函數(shù)方式實(shí)現(xiàn),大家參考使用吧

遇到一個多線程任務(wù)優(yōu)化的問題,現(xiàn)在解決了,分享如下。

假設(shè)有四個任務(wù):

任務(wù)1:登陸驗證(CheckUser)

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

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

任務(wù)4:使用2、3的數(shù)據(jù)執(zhí)行一個方法 (StartProcess)

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

復(fù)制代碼 代碼如下:

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

但是仔細(xì)分析需求我們會發(fā)現(xiàn),任務(wù)2和任務(wù)3并沒有先后區(qū)別,事實(shí)上兩者并無關(guān)聯(lián),只不過任務(wù)4的執(zhí)行需要任務(wù)2和3都已完成作為條件,所以我們可以再開兩個線程用于執(zhí)行任務(wù)2和任務(wù)3,當(dāng)兩者都執(zhí)行完畢之后,執(zhí)行任務(wù)4。

在這里使用了兩個全局變量用于表示任務(wù)2和任務(wù)3的狀態(tài)。用三個線程分別執(zhí)行任務(wù)2、3、4,其中任務(wù)4一直在循環(huán)監(jiān)聽全局變量的狀態(tài),確保在2、3都執(zhí)行完畢后才執(zhí)行。

這記為方法2:

復(fù)制代碼 代碼如下:

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

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

事實(shí)上,Thread類本身已經(jīng)擁有對這種情況的完美解決方案——join。

復(fù)制代碼 代碼如下:

Thread.Join 方法
在繼續(xù)執(zhí)行標(biāo)準(zhǔn)的 COM 和 SendMessage 消息泵處理期間,阻塞調(diào)用線程,直到某個線程終止為止。

簡單來說,join就是個阻塞方法,在線程1內(nèi)創(chuàng)建線程2,調(diào)用線程2的Join方法,那么線程1將會被阻塞,直到線程2執(zhí)行完畢。運(yùn)用到上面的例子就是,在任務(wù)4內(nèi)創(chuàng)建任務(wù)2和任務(wù)3的線程,調(diào)用任務(wù)2和任務(wù)3的線程的Join方法使任務(wù)4阻塞,直到任務(wù)2和任務(wù)3執(zhí)行完畢,才繼續(xù)執(zhí)行任務(wù)4。這記為方法3,代碼如下

復(fù)制代碼 代碼如下:

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


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

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

復(fù)制代碼 代碼如下:

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

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

復(fù)制代碼 代碼如下:

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

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

方法當(dāng)然有:異步委托+回調(diào)函數(shù)

復(fù)制代碼 代碼如下:

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

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

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

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

復(fù)制代碼 代碼如下:

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

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

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

另外,還可以使用觀察者模式實(shí)現(xiàn)異步委托+回調(diào)函數(shù)的效果。

相關(guān)文章

  • C#中GridView動態(tài)添加列的實(shí)現(xiàn)方法

    C#中GridView動態(tài)添加列的實(shí)現(xiàn)方法

    這篇文章主要介紹了C#中GridView動態(tài)添加列的實(shí)現(xiàn)方法,涉及C#中GridView的相關(guān)使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • C#連接數(shù)據(jù)庫的方法

    C#連接數(shù)據(jù)庫的方法

    ASP.NET連接數(shù)據(jù)庫的技術(shù)叫ADO.NET,它是用來向數(shù)據(jù)庫提交sql語句的一堆類。這里連接的是Sql Server 2008數(shù)據(jù)庫,其他數(shù)據(jù)庫用法差不多,就是調(diào)用的類名不一樣
    2015-11-11
  • UGUI輪播圖組件實(shí)現(xiàn)方法詳解

    UGUI輪播圖組件實(shí)現(xiàn)方法詳解

    這篇文章主要為大家詳細(xì)介紹了UGUI輪播圖組件的實(shí)現(xiàn)方法,支持自動輪播、手勢切換等功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-03-03
  • C#心跳機(jī)制客戶端的實(shí)現(xiàn)示例

    C#心跳機(jī)制客戶端的實(shí)現(xiàn)示例

    本文主要介紹了C#心跳機(jī)制客戶端,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • 深入分析C#中WinForm控件之Dock順序調(diào)整的詳解

    深入分析C#中WinForm控件之Dock順序調(diào)整的詳解

    本篇文章是對C#中WinForm控件之Dock順序調(diào)整進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • c# 閉包的相關(guān)知識以及需要注意的地方

    c# 閉包的相關(guān)知識以及需要注意的地方

    這篇文章主要介紹了c# 閉包的相關(guān)知識以及需要注意的地方,文中講解非常細(xì)致,代碼幫助大家理解和學(xué)習(xí),感興趣的朋友可以參考下
    2020-06-06
  • C#七大經(jīng)典排序算法系列(上)

    C#七大經(jīng)典排序算法系列(上)

    這篇文章主要為大家詳細(xì)介紹了C#七大經(jīng)典排序算法系列上篇,冒泡排序,快速排序等,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • C#使用異步流高效處理序列數(shù)據(jù)的方法詳解

    C#使用異步流高效處理序列數(shù)據(jù)的方法詳解

    C#中的異步流(Async Streams),異步流是C# 8.0引入的一個新特性,它允許你異步地處理序列數(shù)據(jù),非常適合處理大量數(shù)據(jù)或長時間運(yùn)行的任務(wù),本文給大家介紹了C#使用異步流高效處理序列數(shù)據(jù)的方法步驟,需要的朋友可以參考下
    2024-11-11
  • automation服務(wù)器不能創(chuàng)建對象 解決方法

    automation服務(wù)器不能創(chuàng)建對象 解決方法

    本文主要介紹如何解決“automation服務(wù)器不能創(chuàng)建對象”錯誤,從而解決Visual Studio.Net不能正常使用的問題,需要的朋友可以參考下。
    2016-06-06
  • C#實(shí)現(xiàn)簡單的汽車租賃系統(tǒng)

    C#實(shí)現(xiàn)簡單的汽車租賃系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)汽車租賃系統(tǒng)的具體實(shí)現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-05-05

最新評論

威信县| 扎赉特旗| 法库县| 壤塘县| 呼和浩特市| 福泉市| 丘北县| 汾西县| 新建县| 奉节县| 洛川县| 鄂托克旗| 长乐市| 洛隆县| 吉隆县| 渭南市| 丰原市| 彭水| 怀仁县| 西贡区| 黄大仙区| 嘉义市| 金昌市| 清镇市| 获嘉县| 绥化市| 岑巩县| 澄城县| 威信县| 兰州市| 浠水县| 永城市| 布拖县| 凤阳县| 中方县| 汝州市| 阜康市| 荥阳市| 呼图壁县| 宝清县| 万年县|