1. 程式人生 > 實用技巧 >.NET多執行緒(Thread,ThreadPool,Task,Async與Await)

.NET多執行緒(Thread,ThreadPool,Task,Async與Await)

.NET多執行緒是什麼?

程序與執行緒

程序是一種正在執行的程式。

執行緒是程式中的一個執行流。

多執行緒是指一個程式中可以同時執行多個不同的執行緒來執行不同的任務。

.NET中的執行緒

Thread是建立和控制執行緒的類。

ManagedThreadId是執行緒ID。

CurrentThread是獲取當前正在執行的執行緒。

同步與非同步

同步是呼叫一旦開始,呼叫者必須等到方法呼叫返回後,才能繼續後續的行為。(單執行緒)

非同步呼叫一旦開始,方法呼叫就會立即返回,呼叫者就可以繼續後續的操作。(多執行緒)

.NET中的多執行緒發展

主要有Thread,ThreadPool,Task

Thread就是執行緒,需要自己排程,直接跟系統對接,相對管理比較複雜及效率差。

ThreadPool是Thread的一個升級版,ThreadPool是從執行緒池中獲取執行緒,如果執行緒池中又空閒的元素,則直接呼叫,如果沒有才會建立,而Thread則是會一直建立新的執行緒,要知道開啟一個執行緒就算什麼事都不做也會消耗大約1m的記憶體,是非常浪費效能的。但是ThreadPool提供的介面比較少。

Task和ThreadPool是一樣的,都是從執行緒池中取空閒的執行緒。比ThreadPool呼叫介面更加豐富。目前.Net使用多執行緒管理,應該優先使用Task。

程式碼:

/// <summary>
/// 多執行緒發展歷史
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnHistory_Click(object sender, EventArgs e)
{
    Console.WriteLine($"Thread start id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}");
    var threadStart = new ThreadStart(DoNothing);
    var thread = new Thread(threadStart);
    thread.Start();
    Console.WriteLine($"Thread end id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}");

    Thread.Sleep(3000);
    Console.WriteLine($"ThreadPool start id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}");
    var callback = new WaitCallback(DoNothing);
    ThreadPool.QueueUserWorkItem(callback);
    Console.WriteLine($"ThreadPool end id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}");

    Thread.Sleep(3000);
    Console.WriteLine($"Task start id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}");
    Action action = DoNothing;
    Task task = new Task(action);
    task.Start();
    Console.WriteLine($"Task end id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}");
}

為什麼需要多執行緒?

特點:

  • 卡介面:單執行緒卡,多執行緒不卡
  • 效能好:單執行緒差,多執行緒好(資源換效能)
  • 執行順序:單執行緒順序,多執行緒無序

程式碼:

/// <summary>
/// 同步(單執行緒)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSync_Click(object sender, EventArgs e)
{
    Console.WriteLine($"btnSync_Click start id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}");
    for (int i = 0; i < 5; i++)
    {
        DoNothing();
    }
    Console.WriteLine($"btnSync_Click end id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}");
}

/// <summary>
/// 非同步(多執行緒)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnAsync_Click(object sender, EventArgs e)
{
    Console.WriteLine($"btnAsync_Click start id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}");
    for (int i = 0; i < 5; i++)
    {
        var ts = new ThreadStart(DoNothing);
        var t = new Thread(ts);
        t.Start();
    }
    Console.WriteLine($"btnAsync_Click end id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}");
}

private void DoNothing()
{
    Console.WriteLine($"DoNothing start id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}");
    Thread.Sleep(2000);
    Console.WriteLine($"DoNothing end id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}");
}

如何使用.NET多執行緒?

Task

建立任務

1、通過呼叫任務類建構函式例項化,但通過呼叫其Start()啟動任務。

Task t1 = new Task(action, "alpha");
t1.Start();

2、通過呼叫TaskFactory.StartNew(Action