[英]Replacing threads with tasks
這里是線程和任務的新手:)
因此,我編寫了一個簡單的線程程序,該程序創建了幾個線程並異步運行它們,然后等待它們完成。
然后,我將其更改為任務。 該代碼做完全相同的事情,唯一的變化是我更改了兩個語句。
因此,確實有兩個問題:
謝謝。
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環境中進行異步編程。
- 在下面的代碼中,有什么區別?
差別很大。 Task
是工作單元,它將使用線程池中的一個或多個線程,該線程是根據要計算的估計工作量分配的。 如果有另一個Task
,並且池中有暫停但仍處於活動狀態的線程,而不是旋轉一個新線程(這非常昂貴),而是重用已經創建的一個線程。 多個任務最終可能最終使用同一線程結束(顯然不是同時發生)
簡而言之,基於任務的並行性是:任務就是工作,ThreadPool提供資源來完成這些工作。 結果,更加靈活,靈活的線程/資源利用率,尤其是在針對各種執行環境和資源可用性的通用程序中,例如雲上的VM。
- 我正在努力找出異步/等待。
await
暗示一項任務與另一項任務的依賴關系。 如果您沒有這種情況,除了等待所有步驟完成之外,您正在做什么就足夠了。 如果需要,您也可以通過TPL
來實現,例如ContinueWith
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.