簡體   English   中英

用任務替換線程

[英]Replacing threads with tasks

這里是線程和任務的新手:)

因此,我編寫了一個簡單的線程程序,該程序創建了幾個線程並異步運行它們,然后等待它們完成。

然后,我將其更改為任務。 該代碼做完全相同的事情,唯一的變化是我更改了兩個語句。

因此,確實有兩個問題:

  1. 在下面的代碼中,有什么區別?
  2. 我正在努力找出異步/等待。 我如何將其集成到下面,或者假設所有示例似乎都是一個方法調用另一個都異步/等待返回的方法,這是使用Task進行后台工作的一個不好的例子嗎?

謝謝。

    namespace ConsoleApp1
    {
            class Program
            {
                static void Main(string[] args)
                {
                    ThreadSample();
                    TaskSample();
                }

                private static void ThreadSample()
                {
                    Random r = new Random();
                    MyThreadTest[] myThreads = new MyThreadTest[4];
                    Thread[] threads = new Thread[4];

                    for (int i = 0; i < 4; i++)
                    {
                        myThreads[i] = new MyThreadTest($"T{i}", r.Next(1, 500));
                        threads[i] = new Thread(new ThreadStart(myThreads[i].ThreadSample));
                        threads[i].Start();
                    }
                    for (int i = 0; i < 4; i++)
                    {
                        threads[i].Join();
                    }

                    System.Console.WriteLine("Finished");
                    System.Console.ReadKey();
                }

                private static void TaskSample()
                {
                    Random r = new Random();
                    MyThreadTest[] myTasks = new MyThreadTest[4];
                    Task[] tasks = new Task[4];
                    for (int i = 0; i < 4; i++)
                    {
                        myTasks[i] = new MyThreadTest($"T{i}", r.Next(1, 500));
                        tasks[i] = new Task(new Action(myTasks[i].ThreadSample));
                        tasks[i].Start();
                    }
                    for (int i = 0; i < 4; i++)
                    {
                        tasks[i].Wait();
                    }

                    System.Console.WriteLine("Finished");
                    System.Console.ReadKey();
                }

            }

            class MyThreadTest
            {
                private string name;
                private int interval;

                public MyThreadTest(string name, int interval)
                {
                    this.name = name;
                    this.interval = interval;
                    Console.WriteLine($"Thread created: {name},{interval}");
                }

                public void ThreadSample()
                {
                    for (int i = 0; i < 5; i++)
                    {
                        Thread.Sleep(interval);
                        Console.WriteLine($"{name} At {i} on thread {Thread.CurrentThread.ManagedThreadId}");
                    }
                }

                public void TaskSample()
                {
                    for (int i = 0; i < 5; i++)
                    {
                        Thread.Sleep(interval);
                        Console.WriteLine($"{name} At {i} on thread {Thread.CurrentThread.ManagedThreadId}");
                    }
                }
            }
    }

任務並行庫(TPL)是一個抽象,您不應該嘗試直接將任務與線程進行比較。 Task對象代表異步任務的抽象概念-一段應該異步執行的代碼,它將完成,出錯(引發異常)或被取消。 抽象意味着您可以編寫和使用此類任務,而不必過多地擔心它們如何異步執行。 有很多有用的東西,例如ContinueWith() ,可以用來組成,排序和管理任務。

線程是一種底層系統系統工具,可用於異步運行代碼,但沒有從任務並行庫(TPL)獲得的所有好處。 如果要排序任務或類似的任務,則必須自己編寫代碼。

在示例代碼中,您實際上並沒有直接創建任何線程。 相反,您編寫的Action由系統線程池執行。 當然,可以更改。 TPL抽象層提供了可以擴展的TaskScheduler類-如果您具有某種異步運行代碼的特殊方式,則可以編寫TaskScheduler來與它一起使用TPL。

async / await是100%編譯器糖。 編譯器將async方法分解為塊,每個塊都成為Task ,並且這些塊在狀態機的幫助下順序執行,所有這些都由編譯器生成。 注意事項:默認情況下, await捕獲當前的SynchronizationContext並在該上下文上恢復。 因此,如果您在WPF或Windows窗體中執行此操作,則await后的繼續代碼實際上根本不在線程中運行,而是在UI線程上運行。 您可以通過調用ConfigureAwait(false)禁用此功能。 實際上, async / await主要用於在與主線程同步很重要的UI環境中進行異步編程。

  1. 在下面的代碼中,有什么區別?

差別很大。 Task是工作單元,它將使用線程池中的一個或多個線程,該線程是根據要計算的估計工作量分配的。 如果有另一個Task ,並且池中有暫停但仍處於活動狀態的線程,而不是旋轉一個新線程(這非常昂貴),而是重用已經創建的一個線程。 多個任務最終可能最終使用同一線程結束(顯然不是同時發生)

簡而言之,基於任務的並行性是:任務就是工作,ThreadPool提供資源來完成這些工作。 結果,更加靈活,靈活的線程/資源利用率,尤其是在針對各種執行環境和資源可用性的通用程序中,例如雲上的VM。

  1. 我正在努力找出異步/等待。

await暗示一項任務與另一項任務的依賴關系。 如果您沒有這種情況,除了等待所有步驟完成之外,您正在做什么就足夠了。 如果需要,您也可以通過TPL來實現,例如ContinueWith

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM