2017-06-04 51 views
0

將傳統應用程序移植到異步\ await模式時,我們遇到了一些我們無法跟蹤的奇怪行爲。我們將頁面async指令設置爲true,並向RowDataBound添加事件處理程序。如果EventHandler中的代碼包含等待的呼叫,則在繼續處理下一行之前,不會等待它。WebForms上的異步行爲gridview

這裏是一個攝製,使其更易於理解:

public partial class WorkingCorrectlyWebForm: System.Web.UI.Page 
{ 
    private int _index; 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     var grid = new GridView(); 
     grid.RowDataBound += GridOnRowDataBound; 
     grid.DataSource = new[] 
     { 
      new {Name = "Person1", Age = 23}, 
      new {Name = "Person2", Age = 33}, 
      new {Name = "Person3", Age = 15} 
     }; 

     grid.DataBind(); 
    } 

    private async void GridOnRowDataBound(object sender, GridViewRowEventArgs gridViewRowEventArgs) 
    { 
     if (gridViewRowEventArgs.Row.RowType != DataControlRowType.DataRow) 
      return; 

     var localIndex = ++_index; 

     HttpContext.Current.Response.Write($"starting #{localIndex} <br />"); 

     await Task.Delay(1000); //HERE IS THE PROBLEMATIC LINE 

     //removing the remark from the following line will make code behave "synchronously" as expected. 
     // Task.Delay(1000).Wait(); 

     HttpContext.Current.Response.Write($"exiting #{localIndex} <br />"); 
    } 
} 

此代碼將產生輸出類同這個(而不是命令「開始\退出」每一個項目):

出發#1

起始#2

起始#3

離開#3

離開#1

離開#2

這是爲什麼happeninig?爲什麼我沒有看到有序的「開始」和「退出」消息。

回答

1

如果你想連續的行爲,這應該工作:

private void GridOnRowDataBound(object sender, GridViewRowEventArgs gridViewRowEventArgs) 
    { 
     if (gridViewRowEventArgs.Row.RowType != DataControlRowType.DataRow) 
      return; 

     var localIndex = ++_index; 

     HttpContext.Current.Response.Write($"starting #{localIndex} <br />"); 

     Thread.Sleep(1000); 
     // or    Task.Delay(1000).Wait(); 


     HttpContext.Current.Response.Write($"exiting #{localIndex} <br />"); 
    } 

或嘗試:

private void GridOnRowDataBound(object sender, GridViewRowEventArgs gridViewRowEventArgs) 
    { 
     RegisterAsyncTask(new PageAsyncTask(() => Bob(gridViewRowEventArgs))); 
     HttpContext.Current.Response.Write($"b"); 

    } 

    private async Task Bob(GridViewRowEventArgs gridViewRowEventArgs) 
    { 
     if (gridViewRowEventArgs.Row.RowType != DataControlRowType.DataRow) 
      return; 

     var localIndex = ++_index; 

     HttpContext.Current.Response.Write($"starting #{localIndex} <br />"); 

     await Task.Delay(1000); 

     HttpContext.Current.Response.Write($"exiting #{localIndex} <br />"); 
    } 
+0

的等待Task.Delay(1000)只是對攝製的緣故。這意味着在這種情況下不會等待任何等待呼叫。 – motime

+0

請看我的問題。我在那裏寫道,這是有效的,但我的問題是爲什麼「等待」不像我在這種情況下預期的那樣工作。 – motime

+0

我懷疑這是因爲您已將方法標記爲異步。您希望該方法是異步的嗎? – mjwills