溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C#多線程編程Task如何使用

發(fā)布時間:2022-03-21 09:11:22 來源:億速云 閱讀:472 作者:iii 欄目:開發(fā)技術(shù)

這篇“C#多線程編程Task如何使用”文章的知識點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“C#多線程編程Task如何使用”文章吧。

一、基本概念

Task優(yōu)勢

ThreadPool相比Thread來說具備了很多優(yōu)勢,但是ThreadPool卻又存在一些使用上的不方便,例如:

  • ThreadPool不支持線程的取消、完成、失敗通知等交互性操作;

  • ThreadPool不支持線程執(zhí)行的先后次序;

.NET Framework 在4.0的時候提供了一個功能更強(qiáng)大的概念:Task。Task在ThreadPool的基礎(chǔ)上進(jìn)行了優(yōu)化,并提供了更多的API??聪旅嬉粋€簡單的示例:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace TaskDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // 創(chuàng)建Task
            Task t = new Task(() => 
            {
                Console.WriteLine("任務(wù)開始工作.....");
                Thread.Sleep(5000);
            });
            // 啟動
            t.Start();
            t.ContinueWith((task) => 
            {
                Console.WriteLine("任務(wù)完成,完成時候的狀態(tài)為:");
                Console.WriteLine("IsCanceled={0}\tIsCompleted={1}\tIsFaulted={2}", task.IsCanceled, task.IsCompleted, task.IsFaulted);
            });
            Console.WriteLine("啟動");
            Console.ReadKey();
        }
    }
}

二、Task用法

創(chuàng)建任務(wù)

Task創(chuàng)建的任務(wù)可以分為有返回值和無返回值兩種。

1、使用Task創(chuàng)建無返回值

先看一下Task的定義:

C#多線程編程Task如何使用

可以看到Task構(gòu)造函數(shù)的參數(shù)是Action委托。所以使用Task創(chuàng)建任務(wù)的代碼如下:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace TaskDemo
{
    class Program
    {
        static void Main(string[] args)
        {

            #region 1、使用Task創(chuàng)建任務(wù)
            Task task = new Task(() => TaskMethod("Task 1"));
            Console.WriteLine("before start status:"+task.Status);
            // Task創(chuàng)建的任務(wù)必須調(diào)用start方法才能啟動
            task.Start();
            Console.WriteLine("after start status:" + task.Status);
            #endregion
            Console.ReadKey();
        }

        static void TaskMethod(string name)
        {
            Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
        }
    }
}

程序運(yùn)行結(jié)果:

C#多線程編程Task如何使用

注:任務(wù)的狀態(tài),Start之前為Created,Start之后為WaitingToRun。

2、使用Task.Run方法創(chuàng)建任務(wù)

Task.Run創(chuàng)建的任務(wù)可以執(zhí)行啟動:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace TaskDemo
{
    class Program
    {
        static void Main(string[] args)
        {

            #region 1、使用Task創(chuàng)建任務(wù)
            //Task task = new Task(() => TaskMethod("Task 1"));
            //Console.WriteLine("before start status:"+task.Status);
            //// Task創(chuàng)建的任務(wù)必須調(diào)用start方法才能啟動
            //task.Start();
            //Console.WriteLine("after start status:" + task.Status);
            #endregion

            #region 2、使用Task.Run創(chuàng)建任務(wù)
            Task.Run(() => TaskMethod("Task Run"));
            #endregion
            Console.ReadKey();
        }

        static void TaskMethod(string name)
        {
            Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
        }
    }
}

程序運(yùn)行結(jié)果:

C#多線程編程Task如何使用

3、使用Factory方式創(chuàng)建任務(wù)
using System;
using System.Threading;
using System.Threading.Tasks;

namespace TaskDemo
{
    class Program
    {
        static void Main(string[] args)
        {

            #region 1、使用Task創(chuàng)建任務(wù)
            //Task task = new Task(() => TaskMethod("Task 1"));
            //Console.WriteLine("before start status:"+task.Status);
            //// Task創(chuàng)建的任務(wù)必須調(diào)用start方法才能啟動
            //task.Start();
            //Console.WriteLine("after start status:" + task.Status);
            #endregion

            #region 2、使用Task.Run創(chuàng)建任務(wù)
            // Task.Run(() => TaskMethod("Task Run"));
            #endregion

            #region 3、使用Factory創(chuàng)建任務(wù)
            // 使用Task.Factory創(chuàng)建
            Task.Factory.StartNew(() => TaskMethod("Task 4"));
            //標(biāo)記為長時間運(yùn)行任務(wù),則任務(wù)不會使用線程池,而在單獨(dú)的線程中運(yùn)行。
            Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning);

            // 實(shí)例化TaskFactory對象,然后創(chuàng)建
            TaskFactory factory = new TaskFactory();
            factory.StartNew(() => TaskMethod("Task 6"));


            #endregion
            Console.ReadKey();
        }

        static void TaskMethod(string name)
        {
            Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
        }
    }
}

程序運(yùn)行結(jié)果:

C#多線程編程Task如何使用

4、創(chuàng)建帶返回值的Task

代碼如下:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace TaskDemo
{
    class Program
    {
        static void Main(string[] args)
        {

            #region 1、使用Task創(chuàng)建任務(wù)
            //Task task = new Task(() => TaskMethod("Task 1"));
            //Console.WriteLine("before start status:"+task.Status);
            //// Task創(chuàng)建的任務(wù)必須調(diào)用start方法才能啟動
            //task.Start();
            //Console.WriteLine("after start status:" + task.Status);
            #endregion

            #region 2、使用Task.Run創(chuàng)建任務(wù)
            // Task.Run(() => TaskMethod("Task Run"));
            #endregion

            #region 3、使用Task.Factory創(chuàng)建任務(wù)
            //Task.Factory.StartNew(() => TaskMethod("Task 4"));
            ////標(biāo)記為長時間運(yùn)行任務(wù),則任務(wù)不會使用線程池,而在單獨(dú)的線程中運(yùn)行。
            //Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning);
            #endregion

            #region 4、創(chuàng)建帶返回值的任務(wù)
            TaskMethodReturn("Main Thread Task");
            // 創(chuàng)建帶返回值的Task
            Task<int> task = CreateTask("Task 1");
            // 啟動
            task.Start();
            // 獲取返回值
            int result1 = task.Result;
            Console.WriteLine($"Task 1 Result is:{result1}");
            Task<int> task2 = new Task<int>(() => TaskMethodReturn("Task 2"));
            task2.Start();
            int result2 = task2.Result;
            Console.WriteLine($"Task 2 Result is:{result2}");
            int result3= Task.Run<int>(() => TaskMethodReturn("Task 3")).Result;
            Console.WriteLine($"Task 3 Result is:{result3}");
            int result4 = Task.Factory.StartNew<int>(() => TaskMethodReturn("Task 4")).Result;
            Console.WriteLine($"Task 4 Result is:{result4}");
            #endregion
            Console.ReadKey();
        }

        /// <summary>
        /// 返回一個Task<int>
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        static Task<int> CreateTask(string name)
        {
            // 參數(shù)是Func<int>
            return new Task<int>(() => TaskMethodReturn(name));
        }

        static void TaskMethod(string name)
        {
            Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
        }

        static int TaskMethodReturn(string name)
        {
            Console.WriteLine("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(2));
            return 42;
        }
    }
}

程序運(yùn)行結(jié)果:

C#多線程編程Task如何使用

我們在文章開始的時候說過,Task是基于ThreadPool的,那么怎么證明呢?看下面的代碼:

/// <summary>
/// 測試Task的線程來自于ThreadPool
/// </summary>
static void Test()
{
            // 設(shè)置線程池中最大的線程數(shù)
            ThreadPool.SetMaxThreads(6, 6);
            // 創(chuàng)建Task的集合
            List<Task> taskList = new List<Task>();
            // 創(chuàng)建int類型的集合,用于存放線程ID
            List<int> threadIdList = new List<int>();
            // 使用Task循環(huán)創(chuàng)建50個線程
            for (int i = 0; i < 30; i++)
            {
                int k = i;
                Task task = Task.Run(() => 
                {
                    // 當(dāng)前線程ID加入到集合中
                    threadIdList.Add(Thread.CurrentThread.ManagedThreadId);
                    Console.WriteLine($"this is {k} 循環(huán) ThreadID:{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                    // 休眠
                    Thread.Sleep(200);
                });
                // 把task加入到集合中
                taskList.Add(task);
            }

            // 等待所有的線程執(zhí)行完
            Task.WaitAll(taskList.ToArray());
            // 輸出總數(shù)量
            Console.WriteLine($"線程總數(shù):{threadIdList.Distinct().Count()}");
}

程序運(yùn)行結(jié)果:

C#多線程編程Task如何使用

從結(jié)果中可以看出,Task中的線程確實(shí)是來自于ThreadPool。

三、常見方法

我們以下面的一個例子來講解Task中比較常見的幾個方法。多名開發(fā)者合作開發(fā)一個項目,每個人負(fù)責(zé)一個模塊的開發(fā),我們可以把這個過程認(rèn)為是多線程,代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace TaskDemo
{
    class Program
    {
        static void Main(string[] args)
        {

            #region 1、使用Task創(chuàng)建任務(wù)
            //Task task = new Task(() => TaskMethod("Task 1"));
            //Console.WriteLine("before start status:"+task.Status);
            //// Task創(chuàng)建的任務(wù)必須調(diào)用start方法才能啟動
            //task.Start();
            //Console.WriteLine("after start status:" + task.Status);
            #endregion

            #region 2、使用Task.Run創(chuàng)建任務(wù)
            // Task.Run(() => TaskMethod("Task Run"));
            #endregion

            #region 3、使用Factory創(chuàng)建任務(wù)
            // 使用Task.Factory創(chuàng)建
            //Task.Factory.StartNew(() => TaskMethod("Task 4"));
            ////標(biāo)記為長時間運(yùn)行任務(wù),則任務(wù)不會使用線程池,而在單獨(dú)的線程中運(yùn)行。
            //Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning);

            // 實(shí)例化TaskFactory對象,然后創(chuàng)建
            //TaskFactory factory = new TaskFactory();
            //factory.StartNew(() => TaskMethod("Task 6"));
            #endregion

            #region 4、創(chuàng)建帶返回值的任務(wù)
            //TaskMethodReturn("Main Thread Task");
            //// 創(chuàng)建帶返回值的Task
            //Task<int> task = CreateTask("Task 1");
            //// 啟動
            //task.Start();
            //// 獲取返回值
            //int result1 = task.Result;
            //Console.WriteLine($"Task 1 Result is:{result1}");
            //Task<int> task2 = new Task<int>(() => TaskMethodReturn("Task 2"));
            //task2.Start();
            //int result2 = task2.Result;
            //Console.WriteLine($"Task 2 Result is:{result2}");
            //int result3= Task.Run<int>(() => TaskMethodReturn("Task 3")).Result;
            //Console.WriteLine($"Task 3 Result is:{result3}");
            //int result4 = Task.Factory.StartNew<int>(() => TaskMethodReturn("Task 4")).Result;
            //Console.WriteLine($"Task 4 Result is:{result4}");
            #endregion


            #region 測試Task線程是來自于ThreadPool

            // Test();
            #endregion

            // 合作開發(fā)項目,每個人負(fù)責(zé)一個模塊,可以認(rèn)為是多線程
            Console.WriteLine("開始合作開發(fā)一個大項目!");
            Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!"));
            Task.Run(() => CodingShow("Kevin", "微信接口!"));
            Task.Run(() => CodingShow("Jack", "搭建后臺框架!"));
            Task.Run(() => CodingShow("Alex", "設(shè)計數(shù)據(jù)庫!"));
            Task.Run(() => CodingShow("Lee", "支付寶接口對接!"));





            Console.ReadKey();
        }

        /// <summary>
        /// 返回一個Task<int>
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        static Task<int> CreateTask(string name)
        {
            // 參數(shù)是Func<int>
            return new Task<int>(() => TaskMethodReturn(name));
        }

        static void TaskMethod(string name)
        {
            Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
        }

        static int TaskMethodReturn(string name)
        {
            Console.WriteLine("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(2));
            return 42;
        }

        /// <summary>
        /// 測試Task的線程來自于ThreadPool
        /// </summary>
        static void Test()
        {
            // 設(shè)置線程池中最大的線程數(shù)
            ThreadPool.SetMaxThreads(6, 6);
            // 創(chuàng)建Task的集合
            List<Task> taskList = new List<Task>();
            // 創(chuàng)建int類型的集合,用于存放線程ID
            List<int> threadIdList = new List<int>();
            // 使用Task循環(huán)創(chuàng)建50個線程
            for (int i = 0; i < 30; i++)
            {
                int k = i;
                Task task = Task.Run(() =>
                {
                    // 當(dāng)前線程ID加入到集合中
                    threadIdList.Add(Thread.CurrentThread.ManagedThreadId);
                    Console.WriteLine($"this is {k} 循環(huán) ThreadID:{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                    // 休眠
                    Thread.Sleep(200);
                });
                // 把task加入到集合中
                taskList.Add(task);
            }

            // 等待所有的線程執(zhí)行完
            Task.WaitAll(taskList.ToArray());
            // 輸出總數(shù)量
            Console.WriteLine($"線程總數(shù):{threadIdList.Distinct().Count()}");
        }

        /// <summary>
        /// 模擬Coding過程
        /// </summary>
        /// <param name="name"></param>
        /// <param name="projectName"></param>
        static void CodingShow(string name, string projectName)
        {
            Console.WriteLine($"CodingShow Start  {name} {projectName}  {Thread.CurrentThread.ManagedThreadId.ToString("00")} ");
            long lResult = 0;
            for (int i = 0; i < 1_000_000_000; i++)
            {
                lResult += i;
            }

            Console.WriteLine($"CodingShow   End  {name} {projectName} {Thread.CurrentThread.ManagedThreadId.ToString("00")} ");
        }
    }
}

程序運(yùn)行結(jié)果:

C#多線程編程Task如何使用

這時需求發(fā)生了變化,所有的模塊都開發(fā)完成以后,開始搭建測試環(huán)境,修改代碼如下:

// 合作開發(fā)項目,每個人負(fù)責(zé)一個模塊,可以認(rèn)為是多線程
Console.WriteLine("開始合作開發(fā)一個大項目!");
Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!"));
Task.Run(() => CodingShow("Kevin", "微信接口!"));
Task.Run(() => CodingShow("Jack", "搭建后臺框架!"));
Task.Run(() => CodingShow("Alex", "設(shè)計數(shù)據(jù)庫!"));
Task.Run(() => CodingShow("Lee", "支付寶接口對接!"));
Console.WriteLine("所有模塊都開發(fā)完成,開始搭建測試環(huán)境");

程序運(yùn)行結(jié)果:

C#多線程編程Task如何使用

可以看到顯然不是我們想要的結(jié)果,模塊開發(fā)工作還沒有結(jié)束就搭建測試環(huán)境,即子線程還沒有結(jié)束,主線程就已經(jīng)結(jié)束了。要想實(shí)現(xiàn)我們想要的效果,那么必須使主線程等待所有子線程都結(jié)束以后,主線程才能結(jié)束。

1、WaitAll()

WaitAll()表示等待所有的Task都執(zhí)行完成??碬aitAll()的定義:

C#多線程編程Task如何使用

WaitAll()方法有很多重載,我們在這里使用第一個重載方法,即參數(shù)是Task[]數(shù)組。查看Run()方法的定義時,我們會發(fā)現(xiàn)Run()方法的返回值就是Task類型,我們使用WaitAll()修改上面的代碼:

// 定義一個Task類型的集合
List<Task> taskList = new List<Task>();
Console.WriteLine("開始合作開發(fā)一個大項目!");
taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!")));
taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺框架!")));
taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計數(shù)據(jù)庫!")));
taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!")));

// 等待所有模塊都開發(fā)完成,才能搭建測試環(huán)境
Task.WaitAll(taskList.ToArray());
Console.WriteLine("所有模塊都開發(fā)完成,開始搭建測試環(huán)境");

程序運(yùn)行結(jié)果:

C#多線程編程Task如何使用

WaitAll()會使程序產(chǎn)生卡頓。

加載首頁信息的時候可以使用WaitAll()方法。一個首頁信息可能來自于幾部分的數(shù)據(jù),每一部分的數(shù)據(jù)對應(yīng)一個線程,只有所有的線程都執(zhí)行完畢才顯示首頁信息。

2、WaitAny()

這時需求又發(fā)生改變了:某一個模塊開發(fā)完成以后就搭建測試環(huán)境。這時候就可以使用WaitAny()了。WaitAny()表示等待其中任何一個任務(wù)完成就會進(jìn)入下一個任務(wù),定義如下:

C#多線程編程Task如何使用

修改后的代碼如下:

// 定義一個Task類型的集合
List<Task> taskList = new List<Task>();
Console.WriteLine("開始合作開發(fā)一個大項目!");
taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!")));
taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺框架!")));
taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計數(shù)據(jù)庫!")));
taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!")));

// 等待所有模塊都開發(fā)完成,才能搭建測試環(huán)境
Task.WaitAny(taskList.ToArray());
Console.WriteLine("有模塊開發(fā)完成,開始搭建測試環(huán)境");

程序運(yùn)行結(jié)果:

C#多線程編程Task如何使用

可以看到:設(shè)計數(shù)據(jù)庫模塊完成以后,就開始搭建測試環(huán)境了。如何需求。

WaitAny()會使程序產(chǎn)生卡頓。

有一個列表數(shù)據(jù),數(shù)據(jù)可以來源于接口、緩存、數(shù)據(jù)庫等,可以開啟多個線程,只要有一個線程執(zhí)行完畢就可以繼續(xù)執(zhí)行下面的步驟,這時就可以使用WaitAny()。

3、ContinueWhenAll()

WaitAll()會卡頓界面,那么有沒有不卡頓界面的呢?ContinueWhenAll和WaitAll實(shí)現(xiàn)的效果一樣,代碼如下:

List<Task> taskList = new List<Task>();
Console.WriteLine("開始合作開發(fā)一個大項目!");
taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!")));
taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺框架!")));
taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計數(shù)據(jù)庫!")));
taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!")));
TaskFactory factory = new TaskFactory();
factory.ContinueWhenAll(taskList.ToArray(), t => Console.WriteLine("所有模塊開發(fā)完成"));

程序運(yùn)行結(jié)果:

C#多線程編程Task如何使用

4、ContinueWhenAny

ContinueWhenAny實(shí)現(xiàn)的效果和WaitAny一樣,ContinueWhenAny不會卡頓界面,代碼如下:

List<Task> taskList = new List<Task>();
Console.WriteLine("開始合作開發(fā)一個大項目!");
taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!")));
taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺框架!")));
taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計數(shù)據(jù)庫!")));
taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!")));
TaskFactory factory = new TaskFactory();
factory.ContinueWhenAny(taskList.ToArray(), t => Console.WriteLine("某一個模塊開發(fā)完成"));

程序運(yùn)行結(jié)果:

C#多線程編程Task如何使用

ContinueWhenAll()和ContinueWhenAny()都會開啟一個新的線程。

5、ContinueWith

ContinueWith表示回調(diào),代碼如下:

Task.Run(() => { Console.WriteLine("任務(wù)執(zhí)行完成"); }).ContinueWith(p=> 
{
      Task.Run(() => { Console.WriteLine("執(zhí)行回調(diào)"); });
});

程序執(zhí)行結(jié)果:

C#多線程編程Task如何使用

程序完整代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace TaskDemo
{
    class Program
    {
        static void Main(string[] args)
        {

            #region 1、使用Task創(chuàng)建任務(wù)
            //Task task = new Task(() => TaskMethod("Task 1"));
            //Console.WriteLine("before start status:"+task.Status);
            //// Task創(chuàng)建的任務(wù)必須調(diào)用start方法才能啟動
            //task.Start();
            //Console.WriteLine("after start status:" + task.Status);
            #endregion

            #region 2、使用Task.Run創(chuàng)建任務(wù)
            // Task.Run(() => TaskMethod("Task Run"));
            #endregion

            #region 3、使用Factory創(chuàng)建任務(wù)
            // 使用Task.Factory創(chuàng)建
            //Task.Factory.StartNew(() => TaskMethod("Task 4"));
            ////標(biāo)記為長時間運(yùn)行任務(wù),則任務(wù)不會使用線程池,而在單獨(dú)的線程中運(yùn)行。
            //Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning);

            // 實(shí)例化TaskFactory對象,然后創(chuàng)建
            //TaskFactory factory = new TaskFactory();
            //factory.StartNew(() => TaskMethod("Task 6"));
            #endregion

            #region 4、創(chuàng)建帶返回值的任務(wù)
            //TaskMethodReturn("Main Thread Task");
            //// 創(chuàng)建帶返回值的Task
            //Task<int> task = CreateTask("Task 1");
            //// 啟動
            //task.Start();
            //// 獲取返回值
            //int result1 = task.Result;
            //Console.WriteLine($"Task 1 Result is:{result1}");
            //Task<int> task2 = new Task<int>(() => TaskMethodReturn("Task 2"));
            //task2.Start();
            //int result2 = task2.Result;
            //Console.WriteLine($"Task 2 Result is:{result2}");
            //int result3= Task.Run<int>(() => TaskMethodReturn("Task 3")).Result;
            //Console.WriteLine($"Task 3 Result is:{result3}");
            //int result4 = Task.Factory.StartNew<int>(() => TaskMethodReturn("Task 4")).Result;
            //Console.WriteLine($"Task 4 Result is:{result4}");
            #endregion


            #region 測試Task線程是來自于ThreadPool

            // Test();
            #endregion

            // 合作開發(fā)項目,每個人負(fù)責(zé)一個模塊,可以認(rèn)為是多線程
            // 無序
            //Console.WriteLine("開始合作開發(fā)一個大項目!");
            //Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!"));
            //Task.Run(() => CodingShow("Kevin", "微信接口!"));
            //Task.Run(() => CodingShow("Jack", "搭建后臺框架!"));
            //Task.Run(() => CodingShow("Alex", "設(shè)計數(shù)據(jù)庫!"));
            //Task.Run(() => CodingShow("Lee", "支付寶接口對接!"));
            //Console.WriteLine("所有模塊都開發(fā)完成,開始搭建測試環(huán)境");

            #region WaitAll
            //// 定義一個Task類型的集合
            //List<Task> taskList = new List<Task>();
            //Console.WriteLine("開始合作開發(fā)一個大項目!");
            //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!")));
            //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
            //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺框架!")));
            //taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計數(shù)據(jù)庫!")));
            //taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!")));

            //// 等待所有模塊都開發(fā)完成,才能搭建測試環(huán)境
            //Task.WaitAll(taskList.ToArray());
            //Console.WriteLine("所有模塊都開發(fā)完成,開始搭建測試環(huán)境");
            #endregion

            #region WaitAny
            // 定義一個Task類型的集合
            //List<Task> taskList = new List<Task>();
            //Console.WriteLine("開始合作開發(fā)一個大項目!");
            //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!")));
            //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
            //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺框架!")));
            //taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計數(shù)據(jù)庫!")));
            //taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!")));

            //// 等待所有模塊都開發(fā)完成,才能搭建測試環(huán)境
            //Task.WaitAny(taskList.ToArray());
            //Console.WriteLine("有模塊開發(fā)完成,開始搭建測試環(huán)境");
            #endregion

            #region ContinueWhenAll
            //List<Task> taskList = new List<Task>();
            //Console.WriteLine("開始合作開發(fā)一個大項目!");
            //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!")));
            //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
            //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺框架!")));
            //taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計數(shù)據(jù)庫!")));
            //taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!")));
            //TaskFactory factory = new TaskFactory();
            //factory.ContinueWhenAll(taskList.ToArray(), t => Console.WriteLine("所有模塊開發(fā)完成"));
            #endregion

            #region ContinueWhenAll
            //List<Task> taskList = new List<Task>();
            //Console.WriteLine("開始合作開發(fā)一個大項目!");
            //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!")));
            //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!")));
            //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺框架!")));
            //taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計數(shù)據(jù)庫!")));
            //taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!")));
            //TaskFactory factory = new TaskFactory();
            //factory.ContinueWhenAny(taskList.ToArray(), t => Console.WriteLine("某一個模塊開發(fā)完成"));
            #endregion

            #region ContinueWith
            Task.Run(() => { Console.WriteLine("任務(wù)執(zhí)行完成"); }).ContinueWith(p=> 
            {
               Task.Run(() => { Console.WriteLine("執(zhí)行回調(diào)"); });
            });
            #endregion



            Console.ReadKey();
        }

        /// <summary>
        /// 返回一個Task<int>
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        static Task<int> CreateTask(string name)
        {
            // 參數(shù)是Func<int>
            return new Task<int>(() => TaskMethodReturn(name));
        }

        static void TaskMethod(string name)
        {
            Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
        }

        static int TaskMethodReturn(string name)
        {
            Console.WriteLine("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(2));
            return 42;
        }

        /// <summary>
        /// 測試Task的線程來自于ThreadPool
        /// </summary>
        static void Test()
        {
            // 設(shè)置線程池中最大的線程數(shù)
            ThreadPool.SetMaxThreads(6, 6);
            // 創(chuàng)建Task的集合
            List<Task> taskList = new List<Task>();
            // 創(chuàng)建int類型的集合,用于存放線程ID
            List<int> threadIdList = new List<int>();
            // 使用Task循環(huán)創(chuàng)建50個線程
            for (int i = 0; i < 30; i++)
            {
                int k = i;
                Task task = Task.Run(() =>
                {
                    // 當(dāng)前線程ID加入到集合中
                    threadIdList.Add(Thread.CurrentThread.ManagedThreadId);
                    Console.WriteLine($"this is {k} 循環(huán) ThreadID:{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                    // 休眠
                    Thread.Sleep(200);
                });
                // 把task加入到集合中
                taskList.Add(task);
            }

            // 等待所有的線程執(zhí)行完
            Task.WaitAll(taskList.ToArray());
            // 輸出總數(shù)量
            Console.WriteLine($"線程總數(shù):{threadIdList.Distinct().Count()}");
        }

        /// <summary>
        /// 模擬Coding過程
        /// </summary>
        /// <param name="name"></param>
        /// <param name="projectName"></param>
        static void CodingShow(string name, string projectName)
        {
            Console.WriteLine($"CodingShow Start  {name} {projectName}  {Thread.CurrentThread.ManagedThreadId.ToString("00")} ");
            long lResult = 0;
            for (int i = 0; i < 1_000_000_000; i++)
            {
                lResult += i;
            }

            Console.WriteLine($"CodingShow   End  {name} {projectName} {Thread.CurrentThread.ManagedThreadId.ToString("00")} ");
        }
    }
}

以上就是關(guān)于“C#多線程編程Task如何使用”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關(guān)的知識內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI