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

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

C#并行編程-Task

2019-11-17 02:57:11
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

C#并行編程-Task

菜鳥(niǎo)學(xué)習(xí)并行編程,參考《C#并行編程高級(jí)教程.PDF》,如有錯(cuò)誤,歡迎指正。

目錄

  • C#并行編程-相關(guān)概念

  • C#并行編程-Parallel

  • C#并行編程-Task

  • C#并行編程-并發(fā)集合

  • C#并行編程-線程同步原語(yǔ)

  • C#并行編程-PLINQ:聲明式數(shù)據(jù)并行

任務(wù)簡(jiǎn)介

TPL引入新的基于任務(wù)的編程模型,通過(guò)這種編程模型可以發(fā)揮多核的功效,提升應(yīng)用程序的性能,不需要編寫(xiě)底層復(fù)雜且重量級(jí)的線程代碼。

但需要注意:任務(wù)并不是線程(任務(wù)運(yùn)行的時(shí)候需要使用線程,但并不是說(shuō)任務(wù)取代了線程,任務(wù)代碼是使用底層的線程(軟件線程,調(diào)度在特定的硬件線程或邏輯內(nèi)核上)運(yùn)行的,任務(wù)與線程之間并沒(méi)有一對(duì)一的關(guān)系。)

創(chuàng)建一個(gè)新的任務(wù)時(shí),調(diào)度器(調(diào)度器依賴于底層的線程池引擎)會(huì)使用工作竊取隊(duì)列找到一個(gè)最合適的線程,然后將任務(wù)加入隊(duì)列,任務(wù)所包含的代碼會(huì)在一個(gè)線程中運(yùn)行。如圖:

System.Threading.Tasks.Task

一個(gè)Task表示一個(gè)異步操作,Task提供了很多方法和屬性,通過(guò)這些方法和屬性能夠?qū)ask的執(zhí)行進(jìn)行控制,并且能夠獲得其狀態(tài)信息。

Task的創(chuàng)建和執(zhí)行都是獨(dú)立的,因此可以對(duì)關(guān)聯(lián)操作的執(zhí)行擁有完全的控制權(quán)。

使用Parallel.For、Parallel.ForEach的循環(huán)迭代的并行執(zhí)行,TPL會(huì)在后臺(tái)創(chuàng)建System.Threading.Tasks.Task的實(shí)例。

使用Parallel.Invoke時(shí),TPL也會(huì)創(chuàng)建與調(diào)用的委托數(shù)目一致的System.Threading.Tasks.Task的實(shí)例。

注意項(xiàng)

程序中添加很多異步的操作作為Task實(shí)例加載的時(shí)候,為了充分利用運(yùn)行時(shí)所有可用的邏輯內(nèi)核,任務(wù)調(diào)度器會(huì)嘗試的并行的運(yùn)行這些任務(wù),也會(huì)嘗試在所有的可用內(nèi)核上對(duì)工作進(jìn)行負(fù)載均衡。

但在實(shí)際的編碼過(guò)程當(dāng)中,并不是所有的代碼片段都能夠方便的用任務(wù)來(lái)運(yùn)行,因?yàn)槿蝿?wù)會(huì)帶來(lái)額外的開(kāi)銷,盡管這種開(kāi)銷比添加線程所帶來(lái)的開(kāi)銷要小,但是仍然需要將這個(gè)開(kāi)銷考慮在內(nèi)。

Task狀態(tài)與生命周期

一個(gè)Task實(shí)例只會(huì)完成其生命周期一次,當(dāng)Task到達(dá)它的3種肯呢過(guò)的最終狀態(tài)之一是,就無(wú)法回到之前的任何狀態(tài)

下面貼代碼,詳解見(jiàn)注釋,方便大家理解Task的狀態(tài):

    class PRogram    {        /*  coder:釋迦苦僧    */        static void Main(string[] args)        {            /*  創(chuàng)建一個(gè)任務(wù) 不調(diào)用 不執(zhí)行  狀態(tài)為Created */            Task tk = new Task(() =>            {            });            Console.WriteLine(tk.Status.ToString());            /*  創(chuàng)建一個(gè)任務(wù) 執(zhí)行  狀態(tài)為 WaitingToRun */            Task tk1 = new Task(() =>            {            });            tk1.Start();/*對(duì)于安排好的任務(wù),就算調(diào)用Start方法也不會(huì)立馬啟動(dòng) 此時(shí)任務(wù)的狀態(tài)為WaitingToRun*/            Console.WriteLine(tk1.Status.ToString());            /*  創(chuàng)建一個(gè)主任務(wù) */            Task mainTask = new Task(() =>            {                SpinWait.SpinUntil(() =>                {                    return false;                }, 30000);            });            /*  將子任務(wù)加入到主任務(wù)完成之后執(zhí)行 */            Task subTask = mainTask.ContinueWith((t1) =>            {            });            /*  啟動(dòng)主任務(wù) */            mainTask.Start();            /*  此時(shí)子任務(wù)狀態(tài)為 WaitingForActivation */            Console.WriteLine(subTask.Status.ToString());            /*  創(chuàng)建一個(gè)任務(wù) 執(zhí)行 后 等待一段時(shí)間 并行未結(jié)束的情況下 狀態(tài)為 Running */            Task tk2 = new Task(() =>            {                SpinWait.SpinUntil(() => false, 30000);            });            tk2.Start();/*對(duì)于安排好的任務(wù),就算調(diào)用Start方法也不會(huì)立馬啟動(dòng)*/            SpinWait.SpinUntil(() => false, 300);            Console.WriteLine(tk2.Status.ToString());            /*  創(chuàng)建一個(gè)任務(wù) 然后取消該任務(wù) 狀態(tài)為Canceled */            CancellationTokenSource cts = new CancellationTokenSource();            Task tk3 = new Task(() =>            {                for (int i = 0; i < int.MaxValue; i++)                {                    if (!cts.Token.IsCancellationRequested)                    {                        cts.Token.ThrowIfCancellationRequested();                    }                }            }, cts.Token);            tk3.Start();/*啟動(dòng)任務(wù)*/            SpinWait.SpinUntil(() => false, 100);            cts.Cancel();/*取消該任務(wù)執(zhí)行 但并非立馬取消 所以對(duì)于Canceled狀態(tài)也不會(huì)立馬生效*/            SpinWait.SpinUntil(() => false, 1000);            Console.WriteLine(tk3.Status.ToString() + " " + tk3.IsCanceled);            SpinWait.SpinUntil(() => false, 1000);            Console.WriteLine(tk3.Status.ToString() + " " + tk3.IsCanceled);            SpinWait.SpinUntil(() => false, 1000);            Console.WriteLine(tk3.Status.ToString() + " " + tk3.IsCanceled);            /*創(chuàng)建一個(gè)任務(wù) 讓它成功的運(yùn)行完成 會(huì)得到 RanToCompletion 狀態(tài)*/            Task tk4 = new Task(() =>            {                SpinWait.SpinUntil(() => false, 10);            });            tk4.Start();            SpinWait.SpinUntil(() => false, 300);            Console.WriteLine(tk4.Status.ToString());            /*創(chuàng)建一個(gè)任務(wù) 讓它運(yùn)行失敗 會(huì)得到 Faulted 狀態(tài)*/            Task tk5 = new Task(() =>            {                throw new Exception();            });            tk5.Start();            SpinWait.SpinUntil(() => false, 300);            Console.WriteLine(tk5.Status.ToString());            Console.ReadLine();        }    }    class Product    {        public string Name { get; set; }        public string Category { get; set; }        public int SellPrice { get; set; }    }
View Code

使用任務(wù)來(lái)對(duì)代碼進(jìn)行并行化

使用Parallel.Invoke可以并行加載多個(gè)方法,使用Task實(shí)例也能完成同樣的工作,下面貼代碼:

    class Program    {        private static ConcurrentQueue<Product> queue = null;        /*  coder:釋迦苦僧    */        static void Main(string[] args)        {            queue = new ConcurrentQueue<Product>();            Task tk1 = new Task(() => { SetProduct(1); SetProduct(3);});            Task tk2 = new Task(() => SetProduct(2));            tk1.Start();            tk2.Start();                                Console.ReadLine();        }        static void SetProduct(int index)        {            Parallel.For(0, 10000, (i) =>            {                Product model = new Product();                model.Name = "Name" + i;                model.SellPrice = i;                model.Category = "Category" + i;                queue.Enqueue(model);            });            Console.WriteLine("SetProduct {0} 執(zhí)行完成", index);        }    }     class Product    {        public string Name { get; set; }        public string Category { get; set; }        public int SellPrice { get; set; }    }
View Code

等待任務(wù)完成Task.WaitAllTask.WaitAll 方法,這個(gè)方法是同步執(zhí)行的,在Task作為參數(shù)被接受,所有Task結(jié)束其執(zhí)行前,主線程不會(huì)繼續(xù)執(zhí)行下一條指令,下面貼代碼

    class Program    {        private static ConcurrentQueue<Product> queue = null;        /*  coder:釋迦苦僧    */        static void Main(string[] args)        {            queue = new ConcurrentQueue<Product>();            Task tk1 = new Task(() => { SetProduct(1); SetProduct(3); });            Task tk2 = new Task(() => SetProduct(2));            tk1.Start();            tk2.Start();            /*等待任務(wù)執(zhí)行完成后再輸出 ====== */            Task.WaitAll(tk1, tk2);            Console.WriteLine("等待任務(wù)執(zhí)行完成后再輸出 ======");            Task tk3 = new Task(() => { SetProduct(1); SetProd
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 辽源市| 贵德县| 金阳县| 息烽县| 舒城县| 南皮县| 江西省| 扎鲁特旗| 大同市| 高邮市| 理塘县| 延边| 巴彦淖尔市| 禄丰县| 长沙县| 弥渡县| 宁国市| 隆林| 新余市| 和田县| 凌源市| 渝中区| 莆田市| 隆林| 阜宁县| 苗栗县| 图们市| 马尔康县| 马边| 西和县| 射阳县| 湖口县| 海安县| 肥西县| 托里县| 通渭县| 莆田市| 商水县| 思茅市| 同德县| 武乡县|