天天看點

Task類學習教程—ContinueWith

Task類學習教程—ContinueWith

一、簡介

通過任務,可以指定在任務完成之後,應開始運作之後另一個特定任務。ContinueWith是Task根據其自身狀況,決定後續應該作何操作。也就是說,在運作完task後,會執行task.continuewith(XX)中的XX語句,但是是否執行、如何執行等需要看task的運作情況。例如:一個使用前一個任務的結果的新任務,如果前一個任務失敗了,這個任務就應執行一些清理工作。任務處理程式都不帶參數或者帶一個對象參數,而任務的連續處理方法都有一個Task類型的參數。

二、案例

案例一:

代碼:

static int TaskMethod(string name, int seconds)
        {
            Console.WriteLine("Frist Task Method : Task {0} is running on a thread id: {1}. Is thread pool thread: {2}",
            name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
            Thread.Sleep(TimeSpan.FromSeconds(seconds));
            return 60 * seconds;
        }
        static void Main(string[] args)
        {

            var FirstTask = new Task<int>(() => TaskMethod("Frist Task", 3));
            FirstTask.ContinueWith(t => Console.WriteLine("Frist Task Result: {0}. Thread id: {1}, Is in Thred Pool: {2}",
            t.Result, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread),
            TaskContinuationOptions.OnlyOnRanToCompletion);//線程池線程
            FirstTask.Start();
           
            Console.ReadKey();
        }      

結果:

Task類學習教程—ContinueWith

Start()和ContinueWith()的先後順序沒有關系,ContinueWith()會等待直到firstTask運作狀态達到 IsCompleted,因為TaskContinuationOptions中的OnlyOnRanToCompletion.必須指出的是,ContinueWith()中的參數是需要以Task為參數的,也就是firstTask作為參數被傳入,而且ContinueWith()運作線上程池中的線程中。我覺得比較重要的一點是:把ContinueWith()中的語句當做一塊新的語句塊,他們獨立于主線程。無論如何,他們都要被判斷,如果狀态(status)不滿足,那麼他們不執行;當指定了多個狀态,則使用合理的對應狀态。

案例二:

class Program
    {
        static int TaskMethod(string name, int seconds)
        {
            Console.WriteLine("Task Method : Task {0} is running on a thread id: {1}. Is thread pool thread: {2}",
            name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
            Thread.Sleep(TimeSpan.FromSeconds(seconds));
            return 60 * seconds;
        }
        static void Main(string[] args)
        {
            Console.WriteLine("Main Thread id {0}, Is in Thred Pool: {1}",
            Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);

            var firstTask = new Task<int>(() => TaskMethod("frist task", 3));
            var secondTask = new Task<int>(() => TaskMethod("second task", 2));

            firstTask.ContinueWith(t => Console.WriteLine("Result:Frist Thread Result: {0}. Thread id: {1}, Is in Thred Pool: {2}",
            t.Result, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread),
            TaskContinuationOptions.OnlyOnRanToCompletion);

            firstTask.Start();
            secondTask.Start();

            Thread.Sleep(TimeSpan.FromSeconds(4)); //給予足夠時間,讓firstTask、secondTask及其後續操作執行完畢。

            Task continuation = secondTask.ContinueWith(t => Console.WriteLine("Result:Second Thread Result: {0}. Thread id: {1}, Is in Thred Pool: {2}",
            t.Result, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread),
            TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously);
            Console.ReadLine();
            Console.ReadKey();
        }
    }      
Task類學習教程—ContinueWith

這裡主線程休眠了足足4秒鐘,足以讓firstTask和secondTask兩個任務完成運作,而後,由于secondTask的後續除了接受OnlyOnRanToCompletion外,還接受ExecuteSynchronously。是以,後續運作中,由于主線程還沒有結束,是以 ExecuteSynchronously得到認可,故secondTask的後續是在主線程上運作。

案例三:

class Program
    {
        static int TaskMethod(string name, int seconds)
        {
            Console.WriteLine("Task Method : Task {0} is running on a thread id: {1}. Is thread pool thread: {2}",
            name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
            Thread.Sleep(TimeSpan.FromSeconds(seconds));
            return 60 * seconds;
        }
        static void Main(string[] args)
        {
            Console.WriteLine("Main Thread id {0}, Is in Thred Pool: {1}",
            Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);

            var firstTask = new Task<int>(() => TaskMethod("frist task", 3));
            var secondTask = new Task<int>(() => TaskMethod("second task", 2));

            firstTask.ContinueWith(t => Console.WriteLine("Result:Frist Thread Result: {0}. Thread id: {1}, Is in Thred Pool: {2}",
            t.Result, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread),
            TaskContinuationOptions.OnlyOnRanToCompletion);

            firstTask.Start();
            secondTask.Start();

           //Thread.Sleep(TimeSpan.FromSeconds(4)); //給予足夠時間,讓firstTask、secondTask及其後續操作執行完畢。

            Task continuation = secondTask.ContinueWith(t => Console.WriteLine("Result:Second Thread Result: {0}. Thread id: {1}, Is in Thred Pool: {2}",
            t.Result, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread),
            TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously);
            Console.ReadLine();
            Console.ReadKey();
        }
    }      
Task類學習教程—ContinueWith

然而,如果把4秒鐘的休眠注釋掉,那麼由于主線程很早就結束了,是以secondTask隻能接受到OnlyOnRanToCompletion,是以還是運作線上程池中。

本文來自部落格園,作者:農碼一生,轉載請注明原文連結:https://www.cnblogs.com/wml-it/p/14845931.html

技術的發展日新月異,随着時間推移,無法保證本部落格所有内容的正确性。如有誤導,請大家見諒,歡迎評論區指正! 個人開源代碼連結: GitHub:

https://github.com/ITMingliang

Gitee:

https://gitee.com/mingliang_it

GitLab:

https://gitlab.com/ITMingliang

進開發學習交流群:
Task類學習教程—ContinueWith

繼續閱讀