我有几个存储过程,可以在ASP.NET Web窗体应用程序中对数据库进行INSERT或UPDATE。我希望执行这些查询,但不希望用户的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);
}
此代码将在引入的延迟之后插入我的测试数据。但是,它将整个页面响应保留给用户,直到延迟结束。理想情况下,我希望页面立即返回给用户,然后五秒钟后,我将在表中看到结果。 ExecuteNonQueryAsync()是错误的工具吗?还是我可以做出一些尚未找到的更改,例如。 “不等”?
答案 0 :(得分:4)
ExecuteNonQueryAsync()似乎正在...阻塞UI,直到两个操作都完成。
是的,这就是ASP.NET的工作方式。所有其他HTTP服务器(例如ASP.NET Core和Node.js)都以相同的方式工作:仅发送一个响应,并且仅在请求处理程序完成时才发送-无论处理程序是同步还是异步,都是如此。
有关更多信息,请参见我的article on async ASP.NET;相关部分:
异步代码不是灵丹妙药
与异步请求处理一样,它不能解决您的所有问题。关于异步和等待可以在ASP.NET上执行的操作,存在一些常见的误解。
当一些开发人员了解异步并等待时,他们认为这是服务器代码“屈服”于客户端(例如浏览器)的一种方式。但是,在ASP.NET上进行异步和等待只能“屈服”到ASP.NET运行时。 HTTP协议保持不变,并且每个请求仍然只有一个响应。如果在异步/等待之前需要SignalR或AJAX或UpdatePanel,则在异步/等待之后仍需要SignalR或AJAX或UpdatePanel。
解决此问题的正确方法是使用reliable queue with an independent background processing application。您的Web请求处理程序仅将一个项目放入队列中,然后快速返回给客户。然后,后台应用程序处理该队列并进行实际的数据库更改。