![](/img/trans.png)
[英]Using async-await for database queries — how does that save threads?
[英]Using async-await for database queries
我目前正在開發一個 ASP NET web api 項目,該項目以異步方式對數據庫進行所有調用。
我們正在使用ServiceStack.OrmLite ,它為我們提供了一個異步和同步的 API 來進行數據庫調用。
我們這樣做的例子:
選項1
var activity = await context.SingleByIdAsync<Activity>(x => x.Id == myId);
var place = await context.SingleByIdAsync<Place>(x => x.Id == myId);
但我們也可以這樣實現。
選項 2
var activity = context.SingleById<Activity>(x => x.Id == myId);
var place = context.SingleById<Place>(x => x.Id == myId);
根據我對異步編程的了解,使用選項 1 我們阻塞線程並在操作完成時釋放它。
我認為選項 1 比選項 2 更昂貴。
Go 進入阻塞等待 - Thread.Sleep、Task.Wait 等。這意味着您在線程 A 上觸發數據庫請求,然后在該線程上輸入等待:線程已分配但被阻塞且不能用於其他任何事情。 當您的數據准備就緒時,您會以某種方式了解到這一點並退出等待,您的代碼會繼續在線程 A 上運行。
最好的方法是什么?
對數據庫調用使用異步操作有什么好處?
我們是否正確地實現了異步調用?
如果我將對數據庫的所有調用切換為同步,我會遇到問題嗎?
最好的方法是什么?
這么少的代碼很難說出來,但一般來說,如果您願意更改調用堆棧中的所有方法並且有適當的異步方法可用,請使用它。
我所說的更改調用堆棧中的所有方法的意思是,如果您將方法TA()
更改為異步(即async Task<T> AAsync()
那么您還必須將任何調用A
的方法也更改為異步.
我所說的正確異步方法是什么意思:在 ASP.Net 的情況下,沒有 UI 線程,因此同步方法會阻塞哪個線程並不重要。 因此,在這種情況下,適當的異步方法將是執行一些異步 IO 並且不阻塞任何線程(甚至不是某些線程池線程)的方法。
對數據庫調用使用異步操作有什么好處?
一般來說,在 ASP.Net 中使用異步的好處是,當請求異步等待某個(正確的)異步操作完成時,它不會阻止任何線程處理另一個請求。
因此,只要您使用的打包程序將數據庫調用實現為適當的異步 IO,您將受益於您的服務器具有更好的可擴展性(即它可以並行處理更多請求)。
我們是否正確地實現了異步調用?
很難從這么少的代碼中分辨出來,但只要您不在調用堆棧中使用Task.Wait()
,您可能會使用它來糾正。
如果我將對數據庫的所有調用切換為同步,我會遇到問題嗎?
如 2. 中所述,當同時完成兩個多個請求時,您可能會遇到問題。
你說“從我對異步編程的了解來看,使用選項 1 我們正在阻塞線程並在操作完成時釋放它。” , 則相反。 當一個線程進入await
時,它將異步等待等待的任務完成。 這意味着線程將可以自由地做其他事情。 完成或失敗(有例外)的任務將被安排繼續。 這取決於捕獲的同步上下文。
您還說“我認為選項 1 在我們實施它的方式上比選項 2 更昂貴。” ,這並沒有完全錯誤,因為異步方法內置在 state 機器中,並且會有一點開銷。 但是由於您處於 ASP.Net 上下文中,因此使用異步操作釋放線程以處理其他請求將大大受益。
這是一篇關於在 ASP.Net 上使用異步的文章。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.