新聞中心
閱讀本篇前,讀者需對(duì).NET4 System.Threading.Tasks 以及 Task Schedulers 有一定的了解。如果不是很了解,請(qǐng)查閱以下相關(guān)信息:

創(chuàng)新互聯(lián)擁有10多年成都網(wǎng)站建設(shè)工作經(jīng)驗(yàn),為各大企業(yè)提供網(wǎng)站設(shè)計(jì)制作、做網(wǎng)站服務(wù),對(duì)于網(wǎng)頁(yè)設(shè)計(jì)、PC網(wǎng)站建設(shè)(電腦版網(wǎng)站建設(shè))、重慶APP軟件開(kāi)發(fā)、wap網(wǎng)站建設(shè)(手機(jī)版網(wǎng)站建設(shè))、程序開(kāi)發(fā)、網(wǎng)站優(yōu)化(SEO優(yōu)化)、微網(wǎng)站、申請(qǐng)域名等,憑借多年來(lái)在互聯(lián)網(wǎng)的打拼,我們?cè)诨ヂ?lián)網(wǎng)網(wǎng)站建設(shè)行業(yè)積累了很多網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、網(wǎng)絡(luò)營(yíng)銷經(jīng)驗(yàn),集策劃、開(kāi)發(fā)、設(shè)計(jì)、營(yíng)銷、管理等網(wǎng)站化運(yùn)作于一體,具備承接各種規(guī)模類型的網(wǎng)站建設(shè)項(xiàng)目的能力。
Task: http://msdn.microsoft.com/en-us/library/system.threading.tasks.task%28VS.100%29.aspx
Task Schedulers: http://msdn.microsoft.com/en-us/library/dd997402.aspx
首先回顧相關(guān)場(chǎng)景:最近工作需要一直在.NET4下編寫window service。在WindowsService下使用了多線程相關(guān)技術(shù)。期間就用了到了線程池。使用線程池的目的:在系統(tǒng)中進(jìn)行多線程并發(fā)也擔(dān)心并發(fā)數(shù)量太大影響性能。于是使用線程池進(jìn)行排隊(duì)。一批一批執(zhí)行多線程。當(dāng)我在使用傳統(tǒng)的.NET線程池的過(guò)程中碰見(jiàn)了一些問(wèn)題,請(qǐng)看以下代碼:
- try
- {
- ThreadPool.SetMaxThreads(2, 2);
- for (int i = 0; i < 5; i++)
- {
- ThreadPool.QueueUserWorkItem(new WaitCallback(InvokeThread1), i);
- }
- }
- catch
- {
- Console.WriteLine("error");
- }
這里建立一個(gè)同時(shí)2個(gè)線程并發(fā)的線程池。在上述代碼第7行傳入InvokeThread1方法:
- static void InvokeThread1(object obj) {
- throw new NullReferenceException();
- }
假設(shè)程序發(fā)生異常,這個(gè)異常卻讓整個(gè)程線程池序崩潰了。主程序并未catch到這個(gè)exception。也許您會(huì)說(shuō)這本來(lái)就是這樣的嘛,有什么好貼出來(lái)的。但是在.NET4中我們可以避免掉這個(gè)問(wèn)題。(此時(shí)體現(xiàn)出.NET4的異常強(qiáng)大)。還有個(gè)問(wèn)題有必要提到:如果一次有兩個(gè)線程同時(shí)并發(fā)(一共要執(zhí)行5個(gè)線程,每次并發(fā)2個(gè))。假設(shè)其中一個(gè)線程執(zhí)行過(guò)程中出現(xiàn)了異常,要讓這兩個(gè)線程以外的三個(gè)線程都停止運(yùn)行,來(lái)節(jié)省系統(tǒng)資源。傳統(tǒng)的線程池也許可以做到,但是控制起來(lái)估計(jì)不會(huì)讓你太輕松。但是在.NET4的Task機(jī)制中,這些都得到了妥善的解決,現(xiàn)將以上兩個(gè)問(wèn)題解決方案給出。如果存在不足的地方,請(qǐng)您指出。
一、自定義TaskScheduler
TaskScheduler代碼如下:
自定義TaskScheduler
- //自定義TaskScheduler
- public class CustomTaskScheduler : TaskScheduler, IDisposable
- {
- //調(diào)用Task的線程
- Thread[] _Threads;
- //Task Collection
- BlockingCollection
_Tasks = new BlockingCollection (); - int _ConcurrencyLevel;
- //設(shè)置schedule并發(fā)
- public CustomTaskScheduler(int concurrencyLevel)
- {
- _Threads = new Thread[concurrencyLevel];
- this._ConcurrencyLevel = concurrencyLevel;
- for (int i = 0; i < concurrencyLevel; i++)
- {
- _Threads[i] = new Thread(() =>
- {
- foreach (Task task in _Tasks.GetConsumingEnumerable())
- this.TryExecuteTask(task);27
- });
- _Threads[i].Start();
- }
- }
- protected override void QueueTask(Task task)
- {
- _Tasks.Add(task);
- }
- protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
- {
- if (_Threads.Contains(Thread.CurrentThread)) return TryExecuteTask(task);
- return false;
- }
- public override int MaximumConcurrencyLevel50 {
- get
- {
- return _ConcurrencyLevel;54 }
- }
- protected override IEnumerable
GetScheduledTasks() - {
- return _Tasks.ToArray();
- }
- public void Dispose()
- {
- this._Tasks.CompleteAdding();
- foreach (Thread t in _Threads)
- {
- t.Join();
- }
- }
- }
該scheduler代碼很簡(jiǎn)單,重寫相關(guān)System.Threading.Tasks.TaskScheduler類下的相關(guān)方法即可,代碼中已給出相關(guān)注釋。
二、使用自定義的TaskScheduler
調(diào)用TaskScheduler代碼:
- List
listMsg = new List () { "Task1", "Task2", "Task3", "Task4", "Task5", "Task6" }; - List
listTask = new List (); - foreach (string msg in listMsg)
- {
- Task myTask = new Task(obj => InvokeThread2((string)obj), msg, token);
- listTask.Add(myTask);
- myTask.Start(customTaskScheduler);
- }
- try
- {
- //等待所有線程全部運(yùn)行結(jié)束
- Task.WaitAll(listTask.ToArray());
- }
- catch (AggregateException ex)
- {
- //.NET4 Task的統(tǒng)一異常處理機(jī)制
- foreach (Exception inner in ex.InnerExceptions)
- {
- Console.WriteLine("Exception type {0} from {1}",
- inner.GetType(), inner.Source);
- }
- }
- Console.ReadLine();
InvokeThread2 相關(guān)代碼:
- static void InvokeThread2(string msg)
- {
- try
- {
- var x = Convert.ToInt32(msg.Replace("Task", "").Trim());
- Console.WriteLine(msg);
- Thread.Sleep(1000 * 5);
- Console.WriteLine("{0} ok", msg); }
- catch (Exception ex)
- {
- //如果有異常發(fā)生則取消正在排隊(duì)的所有線程。
- tokenSource.Cancel();
- Exception exception = new Exception("error");
- exception.Source = msg;
- throw exception;
- } }
以上代碼運(yùn)行效果如下:
接著在TaskScheduler調(diào)用代碼中如果將第一行代碼listMsg值修改成 List
這個(gè)運(yùn)行結(jié)果重點(diǎn)要強(qiáng)調(diào)的地方為:后面這7個(gè)exception。聰明的您或許已經(jīng)看出來(lái)前6個(gè)exception屬于沒(méi)有執(zhí)行的"Task4", "Task5", "Task6", "Task7", "Task8", "Task9",而最后一個(gè)exception才是真正的發(fā)生異常的"TaskA"。這里主要用到了Task的統(tǒng)一異常處理機(jī)制AggregateException??梢詮倪\(yùn)行結(jié)果得到:Task1,Task2,Task3執(zhí)行成功了,但是TaskA發(fā)生了異常導(dǎo)致了后面排隊(duì)的"Task4", "Task5", "Task6", "Task7", "Task8", "Task9"都不會(huì)執(zhí)行了。節(jié)省了系統(tǒng)資源,同時(shí)也提高了系統(tǒng)性能。
三、小結(jié)
本文主要用到了的是.NET4 的Task相關(guān)技術(shù),Task讓我們?cè)诙嗪瞬⑿锌刂频臅r(shí)候更加簡(jiǎn)單,功能更加強(qiáng)大。如果需進(jìn)一步了解相關(guān)技術(shù),博客園已經(jīng)有不少教程。微軟的MSDN也提供了很多參考資料。 最后希望本文可以給您的開(kāi)發(fā)帶來(lái)幫助。
原文鏈接:http://www.cnblogs.com/ryanding/archive/2011/03/22/1990799.html
【編輯推薦】
- 微軟發(fā)布新版Windows 7及.NET 4軟件開(kāi)發(fā)工具包
- 詳解.NET 4.0并行計(jì)算支持歷史
- 詳讀.NET 4.0環(huán)境配置
- 詳解.NET 4.0中異常處理方面的新特性
- 三方面詮釋.NET 4.0的新特性
文章名稱:.NET4多核并行中的Task優(yōu)化線程池
分享地址:http://fisionsoft.com.cn/article/dpdhsij.html


咨詢
建站咨詢
