.Net Core WebAPI 基于Task的同步&異步編程快速入門

并行任務(wù)(Task)以及基于Task的異步編程(asynchronously)在.NET Framework早已使用多年,而在微軟新推出的.NET Core 平臺(tái)下也有相同功能的實(shí)現(xiàn),本文將通過(guò).NET Core WebAPI,介紹使用Task.result的同步編程以及使用await的異步編程模型。

Task.Result

Result方法可以返回Task執(zhí)行后的結(jié)果,如下代碼:

[HttpGet]
public static async Task<JObject> GetJsonAsync(Uri uri)
{
  using (var client = new HttpClient())
  {
    var jsonString = await client.GetStringAsync(uri);
    return JObject.Parse(jsonString);
  }
}

public class MyController : ApiController
{
  public string Get()
  {
    var jsonTask = GetJsonAsync(...);
    return jsonTask.Result.ToString();
  }
}

但是如果在ASP.NET Core的webapi中使用result方法來(lái)獲取task輸出值,會(huì)造成當(dāng)前API線程阻塞等待到task執(zhí)行完成后再繼續(xù)進(jìn)行??梢酝ㄟ^(guò)下面代碼來(lái)證明,get方法有一個(gè)線程,調(diào)用一個(gè)新線程執(zhí)行task(taskcaller),在執(zhí)行task時(shí)候由于需要等待task的執(zhí)行結(jié)果,此時(shí)get方法的執(zhí)行線程等待中,直到result結(jié)果輸出,此線程繼續(xù)完成方法。

[HttpGet]
public string Get()
{
    var info = string.Format("api執(zhí)行線程:{0}", Thread.CurrentThread.ManagedThreadId);
    var infoTask = TaskCaller().Result;
    var infoTaskFinished = string.Format("api執(zhí)行線程(task調(diào)用完成后):{0}", Thread.CurrentThread.ManagedThreadId);
    return string.Format("{0},{1},{2}", info, infoTask, infoTaskFinished);
}

private async Task<string> TaskCaller()
{
    await Task.Delay(500);
    return string.Format("task 執(zhí)行線程:{0}", Thread.CurrentThread.ManagedThreadId);
}

代碼執(zhí)行流程

執(zhí)行原理

輸出結(jié)果如下

result

async & await

如果使用await,在調(diào)用 await taskcall() 時(shí)不會(huì)阻塞get主方法線程,主方法線程會(huì)被釋放,新的線程執(zhí)行完成task后繼續(xù)執(zhí)行await后的代碼減少線程切換開(kāi)銷,而之前的線程則空閑了。

[HttpGet]
public async Task<string> Get()
{
   var info = string.Format("api執(zhí)行線程:{0}", Thread.CurrentThread.ManagedThreadId);
   var infoTask = await TaskCaller();
   var infoTaskFinished = string.Format("api執(zhí)行線程(task調(diào)用完成后):{0}", Thread.CurrentThread.ManagedThreadId);
   return string.Format("{0},{1},{2}", info, infoTask, infoTaskFinished);
}

private async Task<string> TaskCaller()
{
   await Task.Delay(500);
   return string.Format("task 執(zhí)行線程:{0}", Thread.CurrentThread.ManagedThreadId);
}

代碼執(zhí)行流程

執(zhí)行流程

輸出結(jié)果如下

await

總結(jié)

Task.result 與 await關(guān)鍵字 具有類似的功能可以獲取到任務(wù)的返回值,但是本質(zhì)上Task.result會(huì)讓外層函數(shù)執(zhí)行線程阻塞直到任務(wù)執(zhí)行完成,而使用await關(guān)鍵字外層函數(shù)線程則不會(huì)阻塞,而是通過(guò)任務(wù)執(zhí)行線程來(lái)執(zhí)行await后的代碼。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容