C# WebForms gridview上的异步行为

C# WebForms gridview上的异步行为,c#,gridview,webforms,C#,Gridview,Webforms,在将遗留应用程序移植到async\Wait模式时,我们遇到了一些无法跟踪的奇怪行为。我们将page async指令设置为true,并将事件处理程序添加到RowDataBound。如果EventHandler中的代码包含等待调用,则在继续处理下一行之前不会等待调用 下面是一个更容易理解的程序: public partial class WorkingCorrectlyWebForm: System.Web.UI.Page { private int _index; protecte

在将遗留应用程序移植到async\Wait模式时,我们遇到了一些无法跟踪的奇怪行为。我们将page async指令设置为true,并将事件处理程序添加到RowDataBound。如果EventHandler中的代码包含等待调用,则在继续处理下一行之前不会等待调用

下面是一个更容易理解的程序:

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


为什么会这样?为什么我看不到有序的启动和退出消息。

如果需要串行行为,这应该可以:

    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 />");
    }

等待任务.Delay1000只是为了重新编程。这意味着在这种情况下,任何等待的电话都不会被等待。请看“我的问题”。我在那里写道,这是可行的,但我的问题是,为什么Wait在这个场景中不能像我预期的那样工作。我怀疑这是因为您已将该方法标记为async。您希望该方法是异步的,有什么特别的原因吗?是的,因为它需要在等待的方法上等待。您不能只使用等待的方法。等等?