最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

ASP.NET 謹用 async/await

 更新時間:2018年01月08日 11:35:10   作者:Beck''s Blog  
這篇文章主要介紹了ASP.NET 應(yīng)用程序?qū)嶋H使用過程中的一些總結(jié), 包括 異常捕獲 、 死鎖 、 應(yīng)用程序崩潰 ,實際使用過程中一不注意就可能掉坑里了

C# 5.0 引入 async/await 關(guān)鍵字,旨在簡化異步編程模型,拋去語法糖就是 Net4.0 的 Task + 狀態(tài)機。其實在處理異步編程使用 Task 還是挺簡單的,不過既然推出了新的語法糖,難免會嘗試一下,然而在使用中卻沒想象中那么單純。以下針對ASP.NET 應(yīng)用程序?qū)嶋H使用過程中的一些總結(jié), 包括 異常捕獲 、 死鎖 、 應(yīng)用程序崩潰 ,實際使用過程中一不注意就可能掉坑里了。

異常捕獲

async 方法有三種返回類型: void、Task、Task

async void

該方式聲明的方法是無法使用 catch 捕獲異常的,所以以下代碼的 try、catch 并沒什么卵用。

private static async void ThrowExceptionAsync()
{
 await Task.Delay(1000);
 throw new Exception("拋個異常玩玩");
}
public static async void CatchAsyncVoidException()
{
 try
 {
  ThrowExceptionAsync();
 }
 catch (Exception ex)
 {
 throw ex;
 }
}

async Task 或 async Task

這兩種方式聲明的方法異常信息會包含Task屬性內(nèi),但前提需要在try里面使用 await 等待。

private static async Task ThrowExceptionAsync()
{
 await Task.Delay(1000);
 throw new Exception("拋個異常玩玩");
}
public static async Task CatchAsyncTaskException()
{
 try
 {
   await ThrowExceptionAsync();
 }
 catch (Exception ex)
 {
 throw ex;
 }
}
TaskScheduler.UnobservedTaskException

未捕獲的 Task 異常信息可以通過設(shè)置全局的TaskScheduler.UnobservedTaskException 來記錄錯誤日志,在 Global.asax 增加如下代碼:

void Application_Start(object sender, EventArgs e)
{
 // 在應(yīng)用程序啟動時運行的代碼
 TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskExceptionException;
}
void TaskScheduler_UnobservedTaskExceptionException(object sender, UnobservedTaskExceptionEventArgs e)
{
 if (e.Exception != null)
 {
 // do something
 }
}

同步上下文

異步編程必然是關(guān)于線程的使用,線程有一個同步上下文的概念,個人認為線程同步上下文是 async/await 遇到最揪心的問題。在現(xiàn)有項目開發(fā)中我們可能想嘗試使用 async/await,但老代碼都是同步方式,這時如果調(diào)用一個聲明為 async 的方法,死鎖和應(yīng)用程序崩潰的問題一不小心就可能出現(xiàn)。

注意:控制臺程序和.Net Core程序 將不會遇到這個問題,它們不需要同步上下文。

死鎖

private static async Task XXXAsync()
{
 await Task.Delay(1000);
  // some code
}
public static void Test()
{
 var task = XXXAsync();
 task.Wait();
}

以上代碼很完美的實現(xiàn)了死鎖。 默認情況下,當 Wait() 未完成的 Task 時,會捕獲當前線程上下文,在 Task 完成時使用該上下文恢復方法的執(zhí)行。 當 async 方法內(nèi)的 await 執(zhí)行完成時,它會嘗試獲取調(diào)用者線程所在的上下文執(zhí)行方法的剩余部分, 但是該上下文已含有一個線程,該線程在等待 async 方法完成。然后它們相互等待對方,然后就沒有然后了,死在那里。

針對死鎖問題的解決方式是增加 ConfigureAwait(false)

// await Task.Delay(1000);
await Task.Delay(1000).ConfigureAwait(false); // 解決死鎖

當 await 等待完成時,它會嘗試在線程池上下文中執(zhí)行 async 方法的剩余部分,因此就不存在死鎖。

應(yīng)用程序崩潰

測試環(huán)境總發(fā)現(xiàn)IIS應(yīng)用程序池總是崩潰,到底是什么原因?當時我們對這個問題也是非常懵逼,代碼看上去并沒什么明顯毛病,試圖欺騙自己應(yīng)該是環(huán)境本身的問題吧,但事實上確實是在代碼中下了毒。通過各種資料查閱和測試,基本可以斷定是同步代碼調(diào)用異步代碼,同步上下文引起的問題。

如果調(diào)用一個 async 方法。如果使用 await 等待,當前線程立馬被釋放回線程池,線程的上下文信息會被保存。如果沒有使用 await(async void 的方法,必然沒有辦法使用 await),調(diào)用 async 方法之后,代碼會繼續(xù)往下執(zhí)行,執(zhí)行完成后當前線程被釋放回線程池,線程的上下文信息不會被保存。當 async 中的異步任務(wù)執(zhí)行完成后,會從線程池中獲取一個線程繼續(xù)執(zhí)行剩余代碼,同時會獲取當初調(diào)用者所在線程的上下文信息(如果當初調(diào)用者所在線程沒有釋放回線程池,上下文信息可以獲取到)。那么問題就來了,如果當初調(diào)用者沒有使用 await 并且 所在線程釋放回線程池了,上下文信息因為沒有被保持下來,就獲取不到了,這時候會拋出異常 未將對象引用設(shè)置到對象的實例 ,經(jīng)過測試這個異常信息并不一定每次都會出現(xiàn),原因和線程的釋放有關(guān),調(diào)用者所在線程的上下文信息存在就不會拋出異常。異常錯誤信息如下,這個異常最終會導致應(yīng)用程序集停止。

在 System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext)
  在 System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
  在 System.Web.LegacyAspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state)
  在 System.Web.LegacyAspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state)
  在 System.Web.LegacyAspNetSynchronizationContext.Post(SendOrPostCallback callback, Object state)
  在 System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.PostAction(Object state)
  在 System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback callback, Object state, Task& currentTask)
--- 引發(fā)異常的上一位置中堆棧跟蹤的末尾 ---
  在 System.Threading.Tasks.AwaitTaskContinuation.<>c.<ThrowAsyncIfNecessary>b__18_0(Object s)
  在 System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
  在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
  在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
  在 System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
  在 System.Threading.ThreadPoolWorkQueue.Dispatch()
  在 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

針對以上異常我們有什么方式可以解決呢?依然是ConfigureAwait(false),在 Task 上加上 ConfigureAwait(false),此設(shè)置代表當 async 中的異步任務(wù)完成后,不讀取當時調(diào)用它的原線程的上下文信息,而是在線程池上下文中執(zhí)行 async 方法的剩余部分。

public static Task XXXAsync()
{
 await Task.Run(() =>
 {
 // some code
 }).ConfigureAwait(false);
}

總結(jié)

以上所述是小編給大家介紹的ASP.NET 謹用 async/await,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • 如何使用Microsoft.Extensions.AI簡化.NET中的AI集成

    如何使用Microsoft.Extensions.AI簡化.NET中的AI集成

    Microsoft.Extensions.AI是一個創(chuàng)新的?.NET?庫,它為平臺開發(fā)人員提供了一個內(nèi)聚的?C#?抽象層,簡化了與大型語言模型(LLMs)和嵌入等AI服務(wù)的交互,本文給大家介紹如何使用Microsoft.Extensions.AI簡化.NET中的AI集成,感興趣的朋友一起看看吧
    2024-11-11
  • .NET  Visual Studio 代碼性能分析工具

    .NET Visual Studio 代碼性能分析工具

    大家都知道性能優(yōu)化對程序員至關(guān)重要,一個小問題可能導致程序癱瘓,這里我就給大家介紹如何使用工具幫助程序員進行代碼性能優(yōu)化,需要的朋友可以參考下
    2015-07-07
  • .NET MD5加密解密代碼解析

    .NET MD5加密解密代碼解析

    這篇文章主要為大家詳細解析了.NET MD5加密解密代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • Asp.Net Mvc2 增刪改查DEMO代碼

    Asp.Net Mvc2 增刪改查DEMO代碼

    接觸mvc也有一段時間了(2.0),也看到園子里很多人在學習,自己也在園子里面看過前輩們寫的博客,確實受益匪淺。本文寫的都是基礎(chǔ)中的基礎(chǔ),僅供想學習MVC的新手們?nèi)腴T之作
    2012-10-10
  • ASP.NET MVC5網(wǎng)站開發(fā)概述(一)

    ASP.NET MVC5網(wǎng)站開發(fā)概述(一)

    這篇文章主要內(nèi)容是ASP.NET MVC5網(wǎng)站開發(fā)實踐的整體概述,分析了開發(fā)環(huán)境、使用的技術(shù)以及項目的整體結(jié)構(gòu),感興趣的小伙伴們可以參考一下
    2015-09-09
  • ASP.NET生成兩個日期范圍內(nèi)隨機時間的實現(xiàn)方法

    ASP.NET生成兩個日期范圍內(nèi)隨機時間的實現(xiàn)方法

    這篇文章主要介紹了ASP.NET生成兩個日期范圍內(nèi)隨機時間的實現(xiàn)方法,通過自定義函數(shù)記錄開始時間與結(jié)束時間確定時間范圍進而生成該時間段的隨機時間,具有一定的參考借鑒價值,需要的朋友可以參考下
    2014-12-12
  • C#時間格式化(Datetime)用法詳解

    C#時間格式化(Datetime)用法詳解

    C#時間格式化Datetime.ToString參數(shù)format格式詳細用法,本文將進行介紹,感興趣的朋友可以了解下啊
    2013-01-01
  • asp.net 關(guān)于字符串內(nèi)范圍截取的一點方法總結(jié)

    asp.net 關(guān)于字符串內(nèi)范圍截取的一點方法總結(jié)

    前兩天有一位網(wǎng)友提出了一個字符串內(nèi)截取字符串的問題,除了用普通的字符串截取的方式外,我推薦的是用LINQ方式來截取。兩者實際上差別不是很大,都是采用字符串截取方式,但后者從寫法和觀察效果會比前者簡單實用得多。
    2010-02-02
  • ASP.NET中的URL過濾實現(xiàn)代碼

    ASP.NET中的URL過濾實現(xiàn)代碼

    最近做的一個Web項目需要對URL進行過濾,在網(wǎng)上搜了一下,知道J2EE有個Filter的東西,而在.NET方面,其實也可以實現(xiàn)
    2013-01-01
  • 通過jmeter壓測surging的方法

    通過jmeter壓測surging的方法

    Jmeter是Apache開源的一個使用純Java編寫的壓力測試工具,它最初是為測試web應(yīng)用程序而設(shè)計的,但后來擴展到了其他測試功能,這篇文章主要介紹了通過jmeter壓測surging的相關(guān)知識,需要的朋友可以參考下
    2022-07-07

最新評論

九寨沟县| 镶黄旗| 大邑县| 大石桥市| 庆云县| 甘洛县| 晋宁县| 双辽市| 搜索| 阳东县| 承德市| 元朗区| 福贡县| 湛江市| 年辖:市辖区| 兴和县| 北川| 南部县| 睢宁县| 开封县| 湟中县| 广西| 武乡县| 申扎县| 仙居县| 衡阳市| 上高县| 宣威市| 图们市| 恩施市| 芜湖县| 马尔康县| 嘉善县| 黎城县| 邵武市| 武义县| 普兰县| 浦城县| 荥经县| 寻甸| 星座|