异步执行存储过程而不等待它并阻塞 UI

Tim*_*ver 2 c# sql-server asp.net asynchronous async-await

我有几个存储过程可以插入或更新到我的 ASP.NET Web 表单应用程序中的数据库中。我希望执行这些查询,但我不希望用户的 UI 或页面执行等待它们完成。它们不会花费很长时间(远少于一秒),但用户必须等待页面加载这一秒。

我通常会考虑将日志记录或历史记录插入表中。用户的页面视图不依赖于查询的执行或结果。

我正在尝试使用 .NET 的异步方法,例如 ExecuteNonQueryAsync()。但我认为我在概念上犯了错误。ExecuteNonQueryAsync() 似乎用于并行运行两个或多个长时间运行的数据库操作,并阻塞 UI,直到两个操作都完成。

private async Task<string> DoTransaction()
{
    string value = "";

    using (SqlConnection objCS = DB.AdminNET())
    {
        await objCS.OpenAsync();
        using (SqlTransaction t = objCS.BeginTransaction())
        using (SqlCommand objCommand = new SqlCommand("WAITFOR DELAY '00:00:05'; EXEC logtiming @line", objCS, t))
        {
            try
            {
                objCommand.Parameters.Add("@line", SqlDbType.VarChar).Value = "log me";
                await objCommand.ExecuteNonQueryAsync();
            }
            catch
            {
                t.Rollback();
                throw;
            }

            t.Commit();

            value = "done";
        }
    }

    return value;
}

protected async void Page_Load(object sender, EventArgs e)
{
    await DoTransaction(g);
}
Run Code Online (Sandbox Code Playgroud)

此代码将在引入延迟后插入我的测试数据。但是,它会保留对用户的整个页面响应,直到延迟结束。理想情况下,我希望页面立即返回给用户,然后五秒钟后我会在表中看到我的结果。ExecuteNonQueryAsync() 是错误的工具吗?或者我可以做一些我还没有发现的改变,例如。“不等待”?

Ste*_*ary 6

\n

ExecuteNonQueryAsync() 似乎...阻塞 UI,直到两者都完成。

\n
\n\n

是的,这就是 ASP.NET 的工作原理。所有其他 HTTP 服务器(例如 ASP.NET Core 和 Node.js)都以相同的方式工作:只有一个响应需要发送,并且仅在请求处理程序完成时发送 - 无论处理程序是同步还是异步,都是如此。

\n\n

有关更多信息,请参阅我关于异步 ASP.NET 的文章;相关部分:

\n\n
\n

异步代码不是灵丹妙药

\n\n

尽管异步请求处理很美妙,但它并不能解决您的所有问题。关于 async 和 await 在 ASP.NET 上的作用存在一些常见的误解。

\n\n

当一些开发人员了解async和await时,他们认为\xe2\x80\x99是服务器代码\xe2\x80\x9cyield\xe2\x80\x9d到客户端(例如浏览器)的一种方式。但是,ASP.NET 上的异步和等待仅 \xe2\x80\x9cyield\xe2\x80\x9d 到 ASP.NET 运行时;HTTP 协议保持不变,每个请求仍然只有一个响应。如果您在 async/await 之前需要 SignalR 或 AJAX 或 UpdatePanel,那么在 async/await 之后您\xe2\x80\x99 仍然需要 SignalR 或 AJAX 或 UpdatePanel。

\n
\n\n

解决这个问题的正确方法是拥有一个带有独立后台处理应用程序的可靠队列。您的 Web 请求处理程序仅将一个项目放入队列中并快速返回给您的客户端。然后,后台应用程序处理该队列并执行实际的数据库更改。

\n