欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
《CLR via C#》讀書(shū)筆記

《CLR via C#》讀書(shū)筆記-.NET多線(xiàn)程(五)

作者:zlbcdn

現狀
使用ThreadPool的QueueUserWorkItem方法完成異步操作會(huì )存在兩個(gè)問(wèn)題:
1、系統無(wú)法知道異步操作是否完成
2、無(wú)法獲取異步操作完成時(shí)的返回值
問(wèn)題來(lái)了,那就需要新的解決方案(忽然想起上《通信原理》時(shí)老師講的話(huà),“遇到問(wèn)題,解決問(wèn)題,因此就有了不同的編碼方式”,從調幅,到調頻,再到碼分….,工程領(lǐng)域的主題就是遇到問(wèn)題,解決問(wèn)題!跑題了?。?
為了解決上面提到的問(wèn)題,.NET提出了Task的概念
Task
Task的構造方法如下圖所示:


其中參數有:
Action:.NET內部委托
Object:傳入操作的數值
CancellationToken:協(xié)作式取消的Token
TaskCreationOption:創(chuàng )建Task時(shí)的創(chuàng )建方式選項
對于第四項,其規定TaskScheduler的行為方式,讓TaskScheduler按照規定的方式創(chuàng )建Task。但是,TaskScheduler不一定按照此方式執行。因此這個(gè)參數不是很重要。
對于Task還有一個(gè)特別的地方:Task所使用的線(xiàn)程并不是來(lái)自.NET的線(xiàn)程池,而是新創(chuàng )建的一個(gè)Thread
可返回結果的Task類(lèi)
可以使Task返回結果,這個(gè)時(shí)候需要用到Task<TResult>類(lèi),其就是代表一個(gè)可以有返回值的異步操作。
本類(lèi)的構造函數如下:

其中,Func(TResult)的定義如下:

public delegate TResult Func<out TResult>()
  • 1

具體的例子如下:
假設,操作的代碼如下:

private static int Sum(int n){    int sum=0;    for(;n>0;n--)        checked{sum += n;}    return sum;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

若程序希望獲取操作的返回值,則應該如此使用:

Task<int> t = new Task<int>(n=>Sum((int)n),1000000);t.start();t.wait(); //可以寫(xiě)這句,也可以不寫(xiě)Console.WriteLine(t.Result);
  • 1
  • 2
  • 3
  • 4

在.NET中有兩個(gè)Task類(lèi),一個(gè)是不返回參數的,其參數中使用的是Action委托
可返回結果的Task,其參數是使用的Func<Object,TResult>或者是不帶參數的Func<TResult>
Task的異常
在Task的異步操作中可能會(huì )出現異常,若是使用Task<TResult>,在調用其Wait或Result方法時(shí),異常就會(huì )拋出。若使用的Task,則可以調用wait方法,異常就會(huì )拋出。另外,不管是Task<TResult>還是Task,只要查詢(xún)其Exception屬性,異常也會(huì )拋出。
Task的異常會(huì )被存儲在一個(gè)異常集合中,其名稱(chēng)為AggregateException。其內部有一個(gè)InnerExceptions 的屬性,其定義如下:

public ReadOnlyCollection<Exception> InnerExceptions { get; }
  • 1

通過(guò)定義可以看到其返回結果是一個(gè)異常的集合類(lèi)。因此,可以通過(guò)for循環(huán),完成對每一個(gè)異常的處理
AggregateException還有一個(gè)Handle方法,該方法的定義如下:

public void Handle(Func<Exception,?bool> predicate)
  • 1

(寫(xiě)到這兒,不得不發(fā)出感慨!當初設計.NET的這幫人真他媽厲害?。?
這個(gè)方法的作用就是為AggregateException內包含的每一個(gè)異常都調用一個(gè)回調方法
舉例說(shuō)明:

using System;using System.IO;using System.Threading.Tasks;public class Example{    public static void Main()    {        // This should throw an UnauthorizedAccessException.       try {           var files = GetAllFiles(@"C:\");           if (files != null)              foreach (var file in files)                 Console.WriteLine(file);        }        catch (AggregateException ae) {           //這兒就是一個(gè)遍歷InnerExceptions循環(huán),將內部所有的異常全部遍歷,然后進(jìn)行相應處理           //下面的代碼比較簡(jiǎn)單,可通過(guò)判斷是個(gè)什么異常,從而進(jìn)行下一步的相關(guān)操作           foreach (var ex in ae.InnerExceptions)               //例如:               //if(ex is UnauthorizedAccessException)               //     doSomeThing();                   Console.WriteLine("{0}: {1}", ex.GetType().Name, ex.Message);        }        Console.WriteLine();        // This should throw an ArgumentException.        try {           foreach (var s in GetAllFiles(""))              Console.WriteLine(s);        }        catch (AggregateException ae) {           foreach (var ex in ae.InnerExceptions)               Console.WriteLine("{0}: {1}", ex.GetType().Name, ex.Message);        }    }    static string[] GetAllFiles(string path)    {       var task1 = Task.Run( () => Directory.GetFiles(path, "*.txt",                                                      SearchOption.AllDirectories));       try {          return task1.Result;       }       catch (AggregateException ae) {          //Handle是傳入一個(gè)異常參數,返回一個(gè)bool的結果,若處理則返回true,否則返回false          //Handle方法應該是一個(gè)遍歷方法,即通過(guò)InnerExceptions屬性,為每一個(gè)異常添加這個(gè)回調方法          ae.Handle( x => { // Handle an UnauthorizedAccessException                            if (x is UnauthorizedAccessException) {                                Console.WriteLine("You do not have permission to access all folders in this path.");                                Console.WriteLine("See your network administrator or try another path.");                            }                            return x is UnauthorizedAccessException;                          });          return Array.Empty<String>();       }   }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

Task的方法關(guān)于阻塞
Task類(lèi)中有幾個(gè)Wait方法:Wait、WaitAny、WaitAll。具體可參考MSDN的方法說(shuō)明:具體的鏈接在這兒,這兒說(shuō)明的是:
不管是哪個(gè)方法,調用這三者方法的任何一個(gè),都會(huì )造成調用線(xiàn)程被阻塞,即等待task完成相關(guān)的操作。
這兒就有一個(gè)區別,之前join方法與wait方法同樣都是讓線(xiàn)程等待,但是內部如何實(shí)現及兩者的區別
.NET中join與wait方法的區別
在.NET中join方法的源碼如下:(查看.NET的源碼的網(wǎng)址在這兒:查看.NET的源碼網(wǎng)址

//Join方法的源代碼[SecuritySafeCritical, HostProtection(SecurityAction.LinkDemand, Synchronization=true, ExternalThreading=true)]public void Join(){    this.JoinInternal();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

JoinInternal的源代碼未知,只知是window內核的方法

[MethodImpl(MethodImplOptions.InternalCall), SecurityCritical, HostProtection(SecurityAction.LinkDemand, Synchronization=true, ExternalThreading=true)]private extern void JoinInternal();
  • 1
  • 2

而wait方法的代碼如下:

//其他的無(wú)關(guān)代碼,關(guān)鍵的一行如下:Thread.SpinWait(Environment.ProcessorCount * (((int) 4) << i));
  • 1
  • 2

而SpinWait是也是window內核的方法,但是通過(guò)名稱(chēng)可以得知,其是一個(gè)自旋的等待。即代表占用CPU的資源,使得線(xiàn)程被掛起。
個(gè)人對join方法的理解,如下圖所示:


如上圖所示,當程序啟動(dòng)后,主線(xiàn)程會(huì )執行,如圖中1所示,聲明一個(gè)task后,task進(jìn)行異步相關(guān)操作,如圖2所示。當主線(xiàn)程到達t1.join()時(shí),主線(xiàn)程機會(huì )掛起(即主線(xiàn)程不釋放資源或同步鎖,進(jìn)入等待狀態(tài),此處不確定是用戶(hù)模式等待還是內核模式等待)(如圖3),然后task線(xiàn)程執行需要完成的操作(如圖4),直到完成(如圖5)。然后主線(xiàn)程才會(huì )執行剩余的內容(如圖6)所示。
個(gè)人對wait方法的理解。
暫未找到.NET中關(guān)于wait方法的詳細說(shuō)明,因此有兩個(gè)疑問(wèn):
1、調用線(xiàn)程(the calling thread)在阻塞時(shí),是否釋放同步鎖[此處個(gè)人認為是不釋放同步鎖]
2、wait方法與join方法的差異
另外,wait方法很有意思,當調用線(xiàn)程遇到t.Wait()語(yǔ)句時(shí), 調用線(xiàn)程并不是就傻傻的被阻塞了,而是先去看看當前線(xiàn)程是否開(kāi)始執行,若當前線(xiàn)程尚未開(kāi)始執行操作,則調用線(xiàn)程就會(huì )將當前線(xiàn)程將要執行的操作加載到調用線(xiàn)程中執行;若當前線(xiàn)程的操作已經(jīng)開(kāi)始執行了,那沒(méi)辦法,調用線(xiàn)程只能被阻塞。
MSDN上有一篇文章wait方法執行邏輯進(jìn)行了詳細說(shuō)明,具體的網(wǎng)址在這兒。
取消任務(wù)
取消任務(wù)是指使用協(xié)作式取消方式取消task。這個(gè)可以根據task的構造器,傳入一個(gè)token。舉例如下:

//構造一個(gè)取消操作對象private CancellationTokenSource cts = new CancellationSource();public static void Main(string[] args){    //定義一個(gè)具有返回結果類(lèi)型的Task<TResult>    Task<int> t=new Task<int>(tempMethod,t.Token);    t.start();    //取消操作    cts.Cancel();    try    {        Console.WriteLine("返執行結果是:"+t.Result);    }    catch(AggregateException ex) //只要是使用了Task,則catch捕獲的異常就應該使用AggregatException,而不是簡(jiǎn)單的使用Exception    {        ex.Handle(e=>e is OperationCanceledException);        Console.WriteLine("Sum操作已經(jīng)完成")    }}//要符合Func委托private static int tempMethod(){    int resultInt=Sum(cts.Token,10000);}private static int Sum(CancellationToken ct,int n){    int sum=0;    for(;n>0;n--)    {        //若請求操作取消操作,則拋出OperationCanceledException        ct.ThrowIfCancellationRequest();        checked{sum+=n;}    }    return sum;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

當任務(wù)完成后,自動(dòng)執行下一個(gè)任務(wù)
通過(guò)wait方法或者是task.Result屬性獲取操作最后的結果,這個(gè)是存在問(wèn)題的。因為這樣做會(huì )阻塞線(xiàn)程(Result屬性的內部就是調用了wait方法)。因此為了避免因阻塞而導致的性能問(wèn)題,.NET提供了一種回調機制,當線(xiàn)程完成操作時(shí),就會(huì )調用callback方法。
特別說(shuō)明,調用callback的線(xiàn)程是一個(gè)新的線(xiàn)程。
而實(shí)現callback的就是ContinueWith方法,ContinueWith方法的定義如下,更多的定義參見(jiàn):MSDN中方法的定義

public Task ContinueWith(    Action<Task, object> continuationAction,    object state,    CancellationToken cancellationToken,    TaskContinuationOptions continuationOptions,    TaskScheduler scheduler)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2、一個(gè)Task對象內部包含了一個(gè)ContinueWith的對象集合。即一個(gè)task對象可以聲明多個(gè)繼續的操作。例如:

    Task t = new Task(Action());    t.ContinueWith(task=>Console.WriteLine("操作1:Task的結果是"+t.Result));    t.ContinueWith(task=>Console.WriteLine("操作2:Task的結果是"+t.Result));    t.ContinueWith(task=>Console.WriteLine("操作3:Task的結果是"+t.Result));
  • 1
  • 2
  • 3
  • 4

當Task的操作完成后,線(xiàn)程池中會(huì )啟用3個(gè)線(xiàn)程處理相應的回調方法。
3、ContinueWith方法中有一參數:TaskContinuationOptions,是指存在某些情況的下才調用,具體參見(jiàn)參數。一般而言,continuewith是通過(guò)創(chuàng )建一個(gè)獨立的task完成回調方法的調用,但是這個(gè)選項中也可以有一個(gè)AttachedToParent選項,使其成為一個(gè)Task的子任務(wù)
創(chuàng )建子任務(wù)
因為task的構造器中只是定義了委托的定義,但沒(méi)有規定符合委托的方法中是否可以創(chuàng )建task。因此可以在task內部創(chuàng )建子任務(wù),但是在創(chuàng )建子任務(wù)的時(shí)候,需要明確子任務(wù)的創(chuàng )建方式,若是正常創(chuàng )建,則新任務(wù)將是獨立的task。想成為task的子任務(wù),可以在task的構造器中使用TaskCreationOptions.AttachedToParent屬性。這樣就相當于子任務(wù)與父任務(wù)綁定在一起,只有當所有的任務(wù)完成時(shí),父任務(wù)才認為是完成了。舉例如下:

//在定義的時(shí)候同步創(chuàng  )建了3個(gè)子線(xiàn)程,并且用了TaskCreationOptions.AttachedToParent屬性Task<int[]> parent = new Task<int[]>(    int[] results=new int[3];    new Task(()=>results[0]=Sum(100),TaskCreationOptions.AttachedToParent).start();    new Task(()=>results[0]=Sum(200),TaskCreationOptions.AttachedToParent).start();    new Task(()=>results[0]=Sum(300),TaskCreationOptions.AttachedToParent).start();    return results;);var ctw = parent.ContinueWith(    parentTask=> Array.ForEach(Console.WriteLine("結果為:"+parentTask.Result)););parent.Start(); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

任務(wù)內部/小節
1、Task所使用的線(xiàn)程默認是創(chuàng )建新線(xiàn)程,而不是使用線(xiàn)程池線(xiàn)程。因此,其資源的占用和消耗要大于ThreadPool.QueueUserWorkItem
2、Task實(shí)現了IDispose接口,因此在用完task時(shí)要調用dispose,以釋放資源。而不要使用GC回收
3、每個(gè)Task有唯一ID,可通過(guò)CurrentID獲取,而CurrentID是一個(gè)可控類(lèi)型的Int32
4、Task在生命周期中會(huì )有幾個(gè)狀態(tài):
4.1 Createed //任務(wù)顯示的創(chuàng )建完??墒褂胹tart方法,手動(dòng)開(kāi)始這個(gè)任務(wù)
4.2 WaitingForActivation //任務(wù)隱式創(chuàng )建。會(huì )自動(dòng)開(kāi)始。例如,通過(guò)continuewith開(kāi)始的任務(wù)
4.3 WaitingToRun //已經(jīng)進(jìn)入調度,尚未開(kāi)始
4.4 Runing
4.5 WaitingForChildrenToComplete
4.6 task最終的結果為:
4.6.1 RanToCompletion
4.6.2 Cancelled
4.6.3 Faulted
5、可以通過(guò)task的Status屬性獲取task的狀態(tài)。同時(shí)Task提供了幾個(gè)屬性:
IsCanceled、IsCompleted、IsFaulted判斷task的狀態(tài)。但是有一個(gè)特殊情況:當Task的狀態(tài)為RanToCompletion、Cancelled、Faulted中的任意狀態(tài)時(shí),調用Task的IsCompleted屬性,其都將返回true。因此判斷一個(gè)task是正常的完成的方式是:

if(task.Status==TaskStatus.RanToCompletion){    //.....}
  • 1
  • 2
  • 3
  • 4

任務(wù)工廠(chǎng)
有時(shí)候會(huì )遇到一種情況,用相同的配置創(chuàng )建多個(gè)Task。一種方法是挨個(gè)創(chuàng )建task;而另外一個(gè)方法就是使用任務(wù)工廠(chǎng)。(個(gè)人認為任務(wù)工廠(chǎng)使用的機會(huì )不會(huì )很多)
任務(wù)工廠(chǎng)同Task,也有兩種方式,TaskFactory、TaskFactory<TResult>。
可以通過(guò)TaskFactory的構造器創(chuàng )建TaskFactory實(shí)例,也可以使用Task類(lèi)的TaskFactory屬性進(jìn)行創(chuàng )建,一般情況是使用后者。
TaskFactory具體的使用方法,可以參考MSDN的資料:TaskFactory
任務(wù)調度器
1、.NET中有多個(gè)類(lèi)型的任務(wù)調度器,其中線(xiàn)程池使用的是“線(xiàn)程池線(xiàn)程任務(wù)調度器”,而GUI(WinForm、WPF、SilverLight)使用的則是“同步上下文任務(wù)調度器”,而通過(guò)不同的任務(wù)調度器所創(chuàng )建的task,其不允許相互操作。因此使用“線(xiàn)程池線(xiàn)程任務(wù)調度器”所創(chuàng )建的線(xiàn)程,不能操作界面(改變標題之類(lèi)的操作),否則就會(huì )爆出InvalidOperationException
但是若希望線(xiàn)程池中的操作可以操作GUI上的元素,則其需通過(guò)TaskScheduler.FromCurrentSynchronizationContext()方法獲得“同步上下文任務(wù)調度器”,在創(chuàng )建task時(shí),將其作為參數傳入。書(shū)中的例子很好,如下:

internal sealed class MyFrom:Form{    //Form的構造器,初始化標題等內容    public MyFrom(){        this.text="同步上下文任務(wù)調度器demo";        visible=true;        width=400;        height=400;    }    //通過(guò)TaskScheduler獲得當前Form的“同步上下文任務(wù)調度器”    private readonly TaskScheduler m_syncContextTaskScheduler=        TaskScheduler.FromCurrentSynchronizationContext();    private CancellationTokeSource cts;    //重寫(xiě)鼠標的點(diǎn)擊方法    protected override void OnMouseClick(MouseEventArgs e){        if(cts!=null){            cts.cancel();            cts=null;        }else{            text="操作開(kāi)始";            cts = new CancellationTokeSource();            //下面的這個(gè)task使用線(xiàn)程池的任務(wù)調度器,也就是默認的任務(wù)調度器              var task = new task(()=>Sum(cts.Token,2000),cts.Token);            task.ContinueWith(                t=>Text="結果為"+t.Result,                CancellationToken.None,                TaskContinuationOptions.OnlyOnRanToCompletion,                syncContextTaskScheduler            );            task.ContinueWith(                t=>Text="操作被取消",                CancellationToken.None,                TaskContinuationOptions.OnlyOnCanceled,                syncContextTaskScheduler            );            task.ContinueWith(                t=>Text="操作失敗",                CancellationToken.None,                TaskContinuationOptions.OnlyOnFaulted,                syncContextTaskScheduler            );        }//else結束        base.OnMouseClick(e);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

代碼簡(jiǎn)單易懂,有一點(diǎn)很有意思。就是傳入的參數中有:CancellationToken.None,這個(gè)很有意思。其本質(zhì)的想法就是,我創(chuàng )建的這個(gè)操作,不想被外界的cancel方法所取消,但是方法中還必須有一個(gè)這個(gè)參數,因此就使用CancellationToken.None。這個(gè)CancellationToken.None會(huì )返回一個(gè)CancellationToken,因其與任何的CancellationTokenSource沒(méi)有任何關(guān)系,因此操作也就不能被取消了
26.4讀書(shū)思考
1、task還是挺耗費資源的,但是又比Thread、ThreadPool等好用,沒(méi)辦法只能使用它
2、在26.4遇到一個(gè)問(wèn)題,join與wait方法區別,有待解答!

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
[深入學(xué)習C#]C#實(shí)現多線(xiàn)程的方式:Task
委托與線(xiàn)程的見(jiàn)解(下)——線(xiàn)程
C#中創(chuàng )建線(xiàn)程的四種方式
C#之Task.ContinueWith使用實(shí)例
C#線(xiàn)程系列講座(1):BeginInvoke和EndInvoke方法
C# 多線(xiàn)程(菜鳥(niǎo)教程及愛(ài)整理)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久