C# task應用實例詳解
Task的應用
Task的MSDN的描述如下:
【Task類的表示單個操作不會返回一個值,通常以異步方式執(zhí)行。
Task對象是一種的中心思想基于任務的異步模式首次引入.NETFramework 4 中。
因為由執(zhí)行工作Task對象通常以異步方式執(zhí)行線程池線程上而不是以同步方式在主應用程序線程中,可以使用Status屬性,并將IsCanceled, IsCompleted,和IsFaulted屬性,以確定任務的狀態(tài)。
大多數(shù)情況下,lambda 表達式用于指定該任務所執(zhí)行的工作量。
對于返回值的操作,您使用Task類?!?/p>
我對于Task的理解是這樣的,Task是FrameWork4引進的新功能,他和ConCurrent命名空間一起被引進,用來替代Thread的使用。
根據(jù)我的使用,個人覺得,他確實比Thead的功能要豐富一些。
下面我們一起看一個最簡單的例子:
using System;
using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;namespace TaskConsole
{ class Program
{ static void Main(string[] args)
{ //當前線程標識 Console.WriteLine(Thread.CurrentThread.GetHashCode());
Task task = new Task(run);
Console.WriteLine("任務標識:" + task.GetHashCode() + ",狀態(tài):" + task.Status);//狀態(tài) task.Start();
Console.WriteLine("任務標識:" + task.GetHashCode() + ",狀態(tài):" + task.Status);//狀態(tài) //任務完成后執(zhí)行新任務
Action ation = new Action(taskStart);
task.ContinueWith(ation);
Console.Read();
} public static void taskStart(Task task)
{
task = new Task(run);
task.Start(); //如果注釋上面兩句話,則任務標識為 task.ContinueWith(ation)中task的任務
Console.WriteLine("任務標識:" + task.GetHashCode() + ",狀態(tài):" + task.Status + ",當前線程:" + Thread.CurrentThread.GetHashCode());//狀態(tài)
} public static void run()
{
Console.WriteLine("this is run");
}
}
}
一,task.GetHashCode(),是獲取Task實例的唯一標識,每個Task都不一樣。
測試發(fā)現(xiàn),Task.GetHashCode()并不等于Thread.CurrentThread.GetHashCode()。
二,task.ContinueWith(),是任務結(jié)束后繼續(xù)執(zhí)行任務的方法,傳一個Action,當任務結(jié)束后,觸發(fā)該Action。
任務剛new出來的時候,task就又狀態(tài)了,是Created,一但運行了,狀態(tài)就是WaitingToRun。
運行結(jié)果如下:

根據(jù)MSDN的說明,Task.State是獲取TaskState的枚舉值,其枚舉值代表的意義如下
|Canceled |該任務已通過對其自身的 CancellationToken 引發(fā) OperationCanceledException 對取消進行了確認,此時該標記處于已發(fā)送信號狀態(tài);或者在該任務開始執(zhí)行之前,已向該任務的 CancellationToken 發(fā)出了信號。 有關更多信息,請參見任務取消。
| Created |該任務已初始化,但尚未被計劃。
| Faulted |由于未處理異常的原因而完成的任務。
| RanToCompletion |已成功完成執(zhí)行的任務。
| Running |該任務正在運行,但尚未完成。
| WaitingForActivation |該任務正在等待 .NET Framework 基礎結(jié)構(gòu)在內(nèi)部將其激活并進行計劃。
| WaitingForChildrenToComplete |該任務已完成執(zhí)行,正在隱式等待附加的子任務完成。
| WaitingToRun |該任務已被計劃執(zhí)行,但尚未開始執(zhí)行。
任務嵌套
任務嵌套就是指在一個任務中又創(chuàng)建了一個任務。
而新建的任務就是子任務。在沒有特殊聲明的情況下,父子任務是一起運行的。
如SimpleNestedTask方法。
父子任務關聯(lián)需要在創(chuàng)建子任務的時候,增加參數(shù)TaskCreationOptions.AttachedToParent。
將父子任務關聯(lián)起來,此時父任務將等待子任務結(jié)束,才會完成。
如果使用Task創(chuàng)建任務,不需要使用TaskCreationOptions.AttachedToParent參數(shù),因為只要父任務使用了子任務的返回結(jié)果,父任務自然就會等待子任務完成。
public class Program
{
static void Main(string[] args)
{
WaitForSimpleNestedTask();
Console.WriteLine("=====================================================");
SimpleNestedTask();
Thread.SpinWait(600000);//等待SimpleNestedTask結(jié)束 再運行
Console.WriteLine("=====================================================");
//SimpleNestedTaskAttachedToParent();
Console.Read();
}
static void WaitForSimpleNestedTask()
{
var outer = Task.Factory.StartNew(() =>
{
Console.WriteLine("Outer1 task executing.");
var nested = Task.Factory.StartNew(() =>
{
Console.WriteLine("Nested1 task starting.");
Thread.SpinWait(5000000);
Console.WriteLine("Nested1 task completing.");
return 42;
});
return nested.Result;
return 1;
});
Console.WriteLine("Outer1 has returned {0}.", outer.Result);
}
static void SimpleNestedTask()
{
var parent = Task.Factory.StartNew(() =>
{
Console.WriteLine("Outer2 task executing.");
var child = Task.Factory.StartNew(() =>
{
Console.WriteLine("Nested2 task starting.");
Thread.SpinWait(500000);
Console.WriteLine("Nested2 task completing.");
});
});
parent.Wait();
Console.WriteLine("Outer2 has completed.");
}
static void SimpleNestedTaskAttachedToParent()
{
var parent = Task.Factory.StartNew(() =>
{
Console.WriteLine("Outer3 task executing.");
var child = Task.Factory.StartNew(() =>
{
Console.WriteLine("Nested3 task starting.");
Thread.SpinWait(500000);
Console.WriteLine("Nested3 task completing.");
}, TaskCreationOptions.AttachedToParent);
});
parent.Wait();
Console.WriteLine("Outer has completed.");
}
ConCurrent的線程安全的
因為,MSDN將在System.Collections.Concurrent命名空間下的集合,都稱為線程安全的集合。
線程安全可以理解為可以被多個線程同時使用的集合,而且同時使用的時候是該集合的值是準確的。
下面舉一個使用線程安全集合的例子,使用的是BlockingCollection。
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ParallelConsole
{
class Program
{
//定義集合大小為51個,也可以不定義大小
static BlockingCollection blocking = new BlockingCollection(51);
static void Main(string[] args)
{
blocking = new BlockingCollection();
Console.WriteLine("當前blocking為:" + blocking.IsCompleted + "設置了集合大小count一樣是0,blocking.Count:" + blocking.Count());
//當前線程標識
Console.WriteLine(Thread.CurrentThread.GetHashCode());
for (int i = 0; i < 3; i++)
{
////如果添加到第3個,就設置添加完成,這時在添加就會拋異常
//if (i == 3)
//{
// blocking.CompleteAdding();
//}
Action action = new Action(run);
Task task = new Task(action,i);
task.RunSynchronously();
}
Console.WriteLine("設置添加完成前:" + blocking.IsAddingCompleted);
//設置添加完成后
blocking.CompleteAdding();
Console.WriteLine("設置添加完成后:" + blocking.IsAddingCompleted);
#region 同步取 取3個
//for (int i = 0; i < 3; i++)
//{
// Action actionTake = new Action(take);
// actionTake();
//}
#endregion
//并發(fā)讀取
#region 并發(fā)步取 取3個
//blocking.IsCompleted 只有當集合被添加進內(nèi)容,然后又都被取光了以后,他才會等于ture,否則都是false
//當IsCompleted為ture時,就不能再取了否則會拋異常
//同時取,結(jié)果是
//blocking:0
//blocking:2
//blocking:1
if (!blocking.IsCompleted)//如果集合沒取光
{
Action actionTake2 = new Action(take);
Parallel.Invoke(actionTake2, actionTake2, actionTake2);
}
#endregion
Console.WriteLine("當前blocking為:" + blocking.IsCompleted + ",blocking數(shù)量為:" + blocking.Count());
//數(shù)據(jù)被取光了以后, blocking.Count()為0
Console.Read();
}
public static void take()
{
//同步取,blocking.Count()會真實的表現(xiàn),而異步取,Count是不準確的,因為我取count的時候,可能集合已經(jīng)又被取出數(shù)據(jù)了,測試10次肯定會出現(xiàn)不真實的情況
Console.WriteLine("blocking:" + blocking.Take() + ",blocking數(shù)量為:" + blocking.Count());
}
public static void run(object i)
{
int currentI = int.Parse(i.ToString());
blocking.TryAdd(currentI);
}
}
}
Parallel
Parallel.Invoke(),并發(fā)調(diào)用Action,可以傳多個Action,也可以傳一個Action數(shù)據(jù)組。
Task
Task(Action,object),這是Task的構(gòu)造方法,接收Action,object是Action的參數(shù),。
task.RunSynchronously(),他是同步運行任務計劃用的,同時他和task.Start()一樣,也可以啟動線程。
BlockingCollection集合
屬性一:IsCompleted,他是表示集合是否有數(shù)據(jù),只有當集合被添加進內(nèi)容,然后又都被取光了以后,他才會等于ture,否則都是false。
屬性一:BlockingCollection.IsAddingCompleted,表示是否添加完成。針對blocking.CompleteAdding()的使用,當調(diào)用了該方法IsAddingCompleted就為true。
方法一:BlockingCollection.blocking.CompleteAdding(),設置IsAddingCompleted用的。
方法二:BlockingCollection.Add,添加一個實體
方法三:BlockingCollection.TryAdd,添加一個實體,我這里用的是這個方法,區(qū)別是,如果添加重復項,他會引發(fā)InvalidOperationException這個異常。
方法四:BlockingCollection.Take,從集合中取一個值,注意,是真的取出來,取出來后,BlockingCollection.cout會減一。
運行結(jié)果如下:

到此這篇關于C# task應用實例的文章就介紹到這了,更多相關c#task應用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
c# 用Dictionary實現(xiàn)日志數(shù)據(jù)批量插入
這篇文章主要介紹了c# 用Dictionary實現(xiàn)日志數(shù)據(jù)批量插入的步驟,幫助大家更好的理解和使用c#中的Dictionary類,感興趣的朋友可以了解下2021-02-02
c#使用htmlagilitypack解析html格式字符串
這篇文章主要介紹了c#使用htmlagilitypack解析html格式字符串的示例,需要的朋友可以參考下2014-03-03
自定義實現(xiàn)Json字符串向C#對象轉(zhuǎn)變的方法
自定義實現(xiàn)Json字符串向C#對象轉(zhuǎn)變的方法,需要的朋友可以參考一下2013-03-03

