不要在 ASP.NET 4.5 Beta 的 Page 類事件上直接使用 async 與 await

來源:互聯網
上載者:User
文章目錄
  •  
  • 發現問題
  • 在事件上直接使用 async 引發的錯誤
  • UseTaskFriendlySynchronizationContext 的作用和錯誤引發的原因
  • 目前正確的寫法

歡迎到我的部落格中閱讀獨立版本:http://www.dozer.cc/2012/03/async-and-await-in-asp-net-beta/

 發現問題

在我的上一篇文章《async 與 await 在 Web 下的應用》中,我提到了 asp.net 4.5 在 Web.Config 中的一個奇怪配置:

<appSettings>  <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /></appSettings>

在 Stack Overflow 上提問後,終於有人回答我了。

看了別人的回複後,才發現了我上篇文章中的問題。

下面代碼中的這種用法是錯誤的:

protected async void Page_Load(object sender, EventArgs e){    WebClient client = new WebClient();    var result1 = await client.DownloadStringTaskAsync("http://www.website.com");    WebClient client2 = new WebClient();    var result2 = await client.DownloadStringTaskAsync(result1);    //do more}

 

在事件上直接使用 async 引發的錯誤碼段一:
public partial class WebForm1 : System.Web.UI.Page{    protected string Msg { get; set; }    protected async void Page_Load(object sender, EventArgs e)    {        using (WebService service = new WebService())        {            Msg = await service.Method1TaskSync();        }    }    protected async void Button_Test_Click(object sender, EventArgs e)    {        using (WebService service = new WebService())        {            Msg = await service.Method2TaskSync();        }    }}

試問,最後的 Msg 的值是什嗎?應該是哪個方法的傳回值?

如果去掉非同步,那答案肯定是 Method2。那加上非同步後呢?

這裡用的是 async 和 await 來實現了非同步,所以邏輯上的先後次序應該和代碼上的先後次序一樣。

但是上述代碼兩個事件會一起執行!導致了一定的問題!

總結一下上面代碼的問題:當頁面中的 Page_Load 事件和別的事件都用了 async 和 await 後會出現執行次序錯誤、死結等問題。它們並不會按次序執行。

 

程式碼片段二:
<appSettings>  <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /></appSettings>

 

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="AsyncAwait.WebForm1"    Async="true" %><!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server">    <title></title></head><body>    <form id="form1" runat="server">    <div>        <%:Msg %>    </div>    </form></body></html>

後端代碼和上面一樣的代碼,只不過把 UseTaskFriendlySynchronizationContext 的配置改成了 true,並且把資料顯示到了頁面上。

執行後發現:根本無法顯示內容,頁面在非同步執行結束前就已經輸出完畢了。

 

UseTaskFriendlySynchronizationContext 的作用和錯誤引發的原因

其實在老外的回答中已經說明了全部,我這裡主要是翻譯+精簡一下。

 

UseTaskFriendlySynchronizationContext 的作用:

之前版本的 asp.net 所使用的非同步不符合 CLR 的規範,而只有 RegisterAsyncTask 這個方法是符合 CLR 規範的。

所以 asp.net 4.5 中,加入這個新的配置是為了禁用掉之前不符合約定的功能,只要把這個配置設定為了 true,別的非同步方案全部會失效。(程式碼片段二主要就是示範了這個現象)

 

引發錯誤的原因:

async 和 await 關鍵字在底層主要是利用 SynchronizationContext 來實現了非同步。(具體原理我也沒研究過)

而這個方案首先不符合 CLR 規範,另外也會引起很多問題。(程式碼片段一主要就是示範了其中一個問題)

 

目前正確的寫法

首先,建議把 UseTaskFriendlySynchronizationContext 設定為 true。

另外,正確的寫法如下:

public partial class WebForm1 : System.Web.UI.Page{    protected string Msg { get; set; }    protected void Page_Load(object sender, EventArgs e)    {        RegisterAsyncTask(new PageAsyncTask(Method1));    }    private async Task Method1()    {        using (WebService service = new WebService())        {            Msg = await service.HelloWorldTaskSync();        }    }    protected void Button_Test_Click(object sender, EventArgs e)    {        RegisterAsyncTask(new PageAsyncTask(Method2));    }    private async Task Method2()    {        using (WebService service = new WebService())        {            Msg = await service.HelloWorldTaskSync();        }    }}

如果需要寫非同步,一定要用 RegisterAsyncTask 方法,實測證明,支援多次調用,而且會按次序執行。

 

老外說了,他們也想直接在事件上加 async 來寫,但是由於技術原因並沒有實現,希望在正式版或者未來的版本中可以實現吧!

 

參考資料:

http://stackoverflow.com/questions/9562836/whats-the-meaning-of-usetaskfriendlysynchronizationcontext

http://social.msdn.microsoft.com/Forums/en-NZ/async/thread/b2e8c51e-2808-46d0-92e9-b825321d0af8

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.