iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0
Software Development

Rust Web API 從零開始系列 第 27

Day27 - 附錄: Rust中的非同步程式設計(1)

  • 分享至 

  • xImage
  •  

接下來幾篇文章要來探討在Rust中的非同步程式設計,主要內容參考Rust的async book,並且與C#中的Task做比較。

rust採取的非同步模型來源自Functional Programming的Future Monad,與C#中的Task概念極為相似,事實上很多語言都是基於這個模型來進行非同步程式設計(FP沒有想像中的遙遠)。我會先從C#的Task開始介紹,並深入rust future的底層實做。

C# 4.0 時期

現在先讓我們回到C# 4.0還不支援async/await的時期,Task的使用方式大概是這樣:

var task = Task.Factory.StartNew(DoSomething);
task.Wait();
Console.WriteLine("task is completed,result is {0}", task.Result);

在上面的範例中,使用執行緒封鎖的方式task.Wait()來等待任務完成,期間會佔用一個執行緒不能做其他事情,其實非常的沒效率,我們可以稍微改一下:

var task = Task.Factory.StartNew(DoSomething);
while(!task.IsCompleted)
{
    DoAnotherthing1();
    DoAnotherthing2();
    DoAnotherthing3();
}
Console.WriteLine("task is completed,result is {0}", task.Result);

在這邊使用一個while迴圈不斷的詢問task是否完成,尚未完成的話執行緒可以先做其他事情,等到task完成後再印出結果(先忽略迴圈的內容會一直被重做)。

Async/Await 語法糖

C# 5.0 就加入了async/await關鍵字,讓我們再改一下程式碼:

var task = DoSomethingAsync();
DoAnotherthing1();
DoAnotherthing2();
DoAnotherthing3();
Console.WriteLine("task is completed,result is {0}", await task);

上面的的這段程式碼中,當呼叫DoSomethingAsync()後就會開始一個非同步任務,同時可以DoAnotherthing,最後等待task的結果,過程中還不會有重複做DoAnotherthing的狀況,一切都歸功於async/await的語法糖。那麼這背後到底隱藏什麼魔法呢?其實就是透過C#的runtime在背景中有一個任務排程器在不斷的替你詢問IsCompleted(好啦沒那麼白痴,通常都是靠類似事件的機制通知排程器任務的進度)。

小節

上面的故事告訴我們,非同步任務的最外面一定是由一個神奇的同步程式處理(就是while的角色),現在我們來回憶一下最一開始建構Axum章節,把tokio的巨集拆開後有一個同步的block_on方法,tokio runtime扮演的角色就是在背後對async方法進行任務調度,在每一個Task完成的時候將非同步程式的進度往前推進。

明天要來介紹rust中的future trait,實做了future trait的東西就相當於C#中的Task。


上一篇
Day26 - 關於Rust開發Web API這件事
下一篇
Day28 - 附錄: Rust中的非同步程式設計(2)
系列文
Rust Web API 從零開始30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言