線程、async/await

Thread屬性:html

CurrentContext 獲取線程正在其中執行的當前上下文。(獲取ContextID)
CurrentCulture 獲取或設置當前線程的區域性。
CurrentPrinciple 獲取或設置線程的當前負責人(對基於角色的安全性而言)。
CurrentThread 獲取當前正在運行的線程。
CurrentUICulture 獲取或設置資源管理器使用的當前區域性以便在運行時查找區域性特定的資源。
ExecutionContext 獲取一個 ExecutionContext 對象,該對象包含有關當前線程的各類上下文的信息。
IsAlive 獲取一個值,該值指示當前線程的執行狀態。
IsBackground 獲取或設置一個值,該值指示某個線程是否爲後臺線程。
IsThreadPoolThread 獲取一個值,該值指示線程是否屬於託管線程池。
ManagedThreadId 獲取當前託管線程的惟一標識符。
Name 獲取或設置線程的名稱。
Priority 獲取或設置一個值,該值指示線程的調度優先級。
ThreadState 獲取一個值,該值包含當前線程的狀態。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 線程優先級別:安全

Highest > AboveNormal > Normal(默認) > BelowNormal > Lowest異步

 

 

Thread方法:async

public void Abort()  在調用此方法的線程上引起 ThreadAbortException,以開始終止此線程的過程。調用此方法一般會終止線程。性能

public static LocalDataStoreSlot AllocateDataSlot() 在全部的線程上分配未命名的數據槽。爲了得到更好的性能,請改用以 ThreadStaticAttribute 屬性標記的字段。ui

public static LocalDataStoreSlot AllocateNamedDataSlot( string name) 在全部線程上分配已命名的數據槽。爲了得到更好的性能, 請改用以 ThreadStaticAttribute 屬性標記的字段。this

public static void BeginCriticalRegion()通知主機執行將要進入一個代碼區域,在該代碼區域內線程停止或未經處理的異常的影響可能會危害應用程序域中的其餘任務。spa

 

 

 

  

 

 

 

 

 

案例:線程

using System;
using System.Threading;

namespace ConsoleApplication2
{
    class Program
    {
        public static void test_one()
        {
            Console.WriteLine("這好似一個子進程...");
            Console.Write("子進程正在準備休眠5秒");
            for (int i = 0; i < 5; i++)
            {
                Thread.Sleep(1000);  // 休眠1秒,單位是毫秒
                Console.Write("");
            }
            Console.WriteLine();
        }
        static unsafe void Main(string[] args)
        {
            /*
            Thread th = Thread.CurrentThread;  // 獲取當前運行的線程
            th.Name = "mainThread";  // 修改線程名字
            Console.WriteLine(th.Name);
            */
            //
            ThreadStart ts = new ThreadStart(test_one);  // 建立將要執行的子進程
            Console.WriteLine("主線程已經建立子進程...");
            Thread cth = new Thread(ts);  // 子進程初始化
            cth.Start();  // 進程執行
        }
    }
}

 

/*
 * 用戶: NAMEJR
 * 日期: 2019/8/4
 * 時間: 10:49
 */
using System;
using System.Threading;

namespace 線程
{
    class Program
    {
        public static void Main(string[] args)
        {
            Thread thread = new Thread(ConsoleText);  // 實例化一個線程
            thread.IsBackground=true;  // true表示將當前線程設置爲前臺進行,執行完主程序會退出。默認爲false,執行完主窗體程序不會退出
            thread.Priority = ThreadPriority.Normal;  // 建議系統設置優先級
            thread.Start();  // 線程開始
            Console.WriteLine("主線程ID:"+thread.ManagedThreadId);
            Console.WriteLine("子線程ID:"+Thread.CurrentThread.ManagedThreadId);
            //thread.Abort();  // 終止線程(通常不用,不得已才用)
            thread.Join();  // 等待線程執行完成,參數爲超時時間
            Console.ReadKey();
        }
        
        public static void ConsoleText()
        {
            while(true)
            {
                Console.WriteLine(DateTime.Now);
                Thread.Sleep(1000);  // 毫秒爲單位
            }
        }
    }
}

 

/*
 * 用戶: NAMEJR
 * 日期: 2019/8/4
 * 時間: 11:54
 */
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace 窗體線程
{
    /// <summary>
    /// Description of MainForm.
    /// </summary>
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }
        
        void Btn_ThreadClick(object sender, EventArgs e)
        {
            // 解決線程間的控件問題
            Thread thread = new Thread(()=>{
                                           // InvokeRequired:用來判斷控件是否由當前線程建立,不是返回true
                                           if(TB_Msg.InvokeRequired){
                                               // TB_Msg.Invoke:Invoke表示找到TB_Msg建立的線程
                                               TB_Msg.Invoke(new Action<string>(s=>{this.TB_Msg.Text=s;}),"當前線程輸入,輸入時間:"+DateTime.Now);
                                           }else{
                                               // 若是不是當前線程建立,那就表示是主窗體線程
                                               this.TB_Msg.Text="窗體線程輸入,輸入時間:"+DateTime.Now;
                                           }
                                       });
            thread.IsBackground=true;
            thread.Start();
        }
    }
}

 

using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.IO;
using System.Windows.Forms;
using System.Threading;
using System.Timers;

namespace 控制檯臨時代碼
{
    class Program
    {
        public static void Main(string[] args)
        {
            // 帶參線程
            Thread thread1 = new Thread(test);
            thread1.IsBackground = true;
            thread1.Start("123");
            thread1.Join();
        }
        // 所帶參數必須爲object
        public static void test(object l_objStr)
        {
            for(int i=0;i<999999;i++)
            {
                Console.WriteLine(l_objStr.ToString());
                Thread.Sleep(1);
            }
        }
    }
}

 

 

ThreadPool線程池:code

公共語言運行庫CRL中的線程池分爲兩種:工做者模式(workerThreads)和I/O模式(completionThreads)。工做者模式主要用來作密集的任務計算;I/O主要用來與外部系統進行交互。

使用線程池的好處:減小系統重複建立線程的響應和分配資源時間,以及資源分配的開銷。缺點:不能再對每一個線程進行監控。(其實每一個語言都差很少)

Add by 2019-9-23

線程池最多管理線程數量=「處理器數 * 250」。也就是說,若是您的機器爲2個2核CPU,那麼CLR線程池的容量默認上限即是1000(這句話來源自:https://www.cnblogs.com/qixuejia/p/7802092.html,做者:Cat Qi,若是想仔細瞭解線程及線程池能夠去看看這個文章)

End Add

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

namespace ConsoleApplication1
{
    class Program
    {
        // 獲取系統信息
        private static void GetSystemInfo(object a_obj)
        {
            IDictionary l_idInfos = System.Environment.GetEnvironmentVariables();
            foreach(DictionaryEntry l_idInfo in l_idInfos)
            {
                Console.WriteLine("系統信息:key={0}, value={1}", l_idInfo.Key, l_idInfo.Value);
            }
            Console.WriteLine("=================");
        }
        static void Main(string[] args)
        {
            ThreadPool.SetMaxThreads(10, 10);  // 設置最大的線程數,第一個參數爲工做者模式,第二個參數爲I/O模式
            ThreadPool.SetMinThreads(5, 5);  // 設置最小線程數
            ThreadPool.GetAvailableThreads(out int a_GetWorkerThreadsNum, out int a_GetCompletionThreadsNum);   // 返回剩餘空閒線程數
            ThreadPool.QueueUserWorkItem(new WaitCallback(GetSystemInfo));  // 將方法排入隊列
        }
    }
}

 這裏的信息不夠詳細,若是想仔細看,請轉往這個大佬的博客:https://www.cnblogs.com/scmail81/p/9503266.html

 Task:

 建立一個簡單地task

class Program
    {
        static void Main(string[] args)
        {
            // 建立task
            Task l_task = new Task(() =>
            {
                Console.WriteLine("正在task內部執行....");
                Thread.Sleep(100);
            });
            l_task.Start();  // 啓動
            l_task.ContinueWith((l_parameter) =>
            {
                // task不一樣於線程池,能夠獲取上一個線程的狀態
                Console.WriteLine("上一個任務的狀態:");
                Console.WriteLine("IsCanceled={0}\tIsCompleted={1}\tIsFaulted={2}", l_parameter.IsCanceled, l_parameter.IsCompleted, l_parameter.IsFaulted);  // IsCanceled(被取消而完成)、IsCompleted(是否已經完成)、IsFaulted(未處理異常而完成)獲取執行狀況
            });
            Console.ReadKey();
        }
    }

關於WaitAll/WaitAny和Task.Factory.StartNew的使用

class Program
    {
        static void Main(string[] args)
        {
            Task l_task1 = new Task(() => Func1("Task1"));
            Task l_task2 = new Task(() => Func1("Task2"));
            l_task2.Start();
            l_task1.Start();
            Task.WaitAll(l_task1, l_task2);  // 等待前兩個(全部)任務完成。Task.WaitAny()等待任何一個任務完成
            Task.Run(() => Func1("Task3"));
            Task.Factory.StartNew(() => Func1("Task4"));  // 建立並啓動任務
            Task.Factory.StartNew(() => Func1("Task5"), TaskCreationOptions.LongRunning);
            
            Console.ReadKey();
        }

        public static void Func1(string name1)
        {
            Console.WriteLine("{0}任務正在執行...", name1);
        }
    }
class Program
    {
        static void Main(string[] args)
        {
            Task<int> l_task1 = Func1();
            //l_task1.RunSynchronously();  // 將當前的task(l_task1)其變成同步運行
            l_task1.Start();
            l_task1.Wait();  // 等待l_task1完成執行
            int l_intResult = l_task1.Result;  // 獲取返回值
            Console.WriteLine(l_intResult.ToString());
            Console.ReadKey();
        }

        public static Task<int> Func1()
        {
            return new Task<int>(()=> { return 1; });
        }
    }
class Program
    {
        // await還能夠適用於組合任務中
        static void Main(string[] args)
        {
            Task<int> l_task1 = new Task<int>(()=> {
                Console.WriteLine("1");
                return 1;
            });
            l_task1.Start();
            Task l_task2 = l_task1.ContinueWith(parameter => {
                Console.WriteLine("2");
                Console.WriteLine(parameter.Result.ToString());
            });
            l_task1.Wait();
            l_task2.Wait();
            Console.ReadKey();
        }
    }

帶參數:

class Program
    {
        static void Main(string[] args)
        {
            Task<int> l_task1 = Func1();
            l_task1.Start();
            int l_intResult = l_task1.Result;  // 獲取返回值
            Console.WriteLine(l_intResult.ToString());
            Console.ReadKey();
        }

        public static Task<int> Func1()
        {
            return new Task<int>(()=> { return 1; });
        }
    }

async/await在Task中的使用

using System.Threading.Tasks;
...
class
Program { static void Main(string[] args) { Console.WriteLine("這是最前面執行的方法..."); Func1(); Console.WriteLine("這是Func1以後的方法"); Console.ReadKey(); } // 異步 public async static void Func1() { await Task.Delay(1000); // 等待,缺乏該方法將會以同步運行的方式,在這裏以毫秒爲單位 Console.WriteLine("這本該是第二個輸出..."); } }
class Program
    {
        static void Main(string[] args)
        {
            Task<int> l_task1 = ReverInt(98541);
            Console.WriteLine("最早輸出...");  // 立馬輸出
            l_task1.Wait();  // 等待l_task1執行完成
            Console.WriteLine("最後輸出...");  // 1秒後輸出
            Console.WriteLine("結果爲:{0}", l_task1.Result);  // 輸出結果
            Console.ReadKey();
        }

        public async static Task<int> ReverInt(int a_intNum)
        {
            int l_intRevNum = 0;
            int l_intTempNum = a_intNum;
            while(l_intTempNum!=0)
            {
                l_intRevNum = l_intRevNum * 10 + l_intTempNum % 10;
                l_intTempNum /= 10;
            }
            await Task.Delay(1000);
            return l_intRevNum;
        }
    }
相關文章
相關標籤/搜索