【发布时间】:2018-08-21 13:26:21
【问题描述】:
我希望 Web 应用程序的用户能够取消服务器端长时间运行的 SQL 查询(通过使用 xhr.abort() 方法)
我正在使用Response.ClientDisconnectedToken 在服务器端捕获用户取消请求的事件(来自这里:https://stackoverflow.com/a/17713153/8790102)
SQL 查询例程在 async 方法中完成(来自这里:https://stackoverflow.com/a/24834029/8790102)
private async Task<DataTable> executeSelectQueryAsync(string SQL, Dictionary<string, object> BindObject = null)
{
// This cancellationToken is tripped when the client abort the request
CancellationToken canceltk = HttpContext.Current.Response.ClientDisconnectedToken; // Require IIS 7.5
DataTable dt = new DataTable();
// Only line to be logged in the server
File.AppendAllText(System.Web.HttpContext.Current.Server.MapPath("~/data/logCanceledRequest.txt"), "CANCELING ENABLED" + Environment.NewLine);
try
{
dt = await Task.Run(() =>
{
// If token is canceled, cancel SQL query
canceltk.Register(() =>
{
File.AppendAllText(System.Web.HttpContext.Current.Server.MapPath("~/data/logCanceledRequest.txt"), "CANCELLING..." + Environment.NewLine);
// scmd is of type OracleCommand
if (scmd.Connection.State == ConnectionState.Open)
scmd.Cancel();
});
// Open the connection, execute the SQL command using OracleDataAdapter.Fill method and return a DataTable
return executeSelectQuery_inner(SQL, BindObject);
}, canceltk);
}
catch (TaskCanceledException ex)
{
try
{
File.AppendAllText(System.Web.HttpContext.Current.Server.MapPath("~/data/logCanceledRequest.txt"), "Cancelling query..." + Environment.NewLine);
if(scmd.Connection.State == ConnectionState.Open)
scmd.Cancel();
}
catch (Exception ex1)
{
File.AppendAllText(System.Web.HttpContext.Current.Server.MapPath("~/data/logCanceledRequest.txt"), "Cancel_ERROR:" + ex1.ToString() + Environment.NewLine);
}
}
catch (Exception ex)
{
File.AppendAllText(System.Web.HttpContext.Current.Server.MapPath("~/data/logCanceledRequest.txt"), "OTHER EXCEPTION:" + ex.ToString() + Environment.NewLine);
}
return dt;
}
我的问题是在中止请求时没有调用canceltk.Register()中注册的方法(没有记录相应的文本“CANCELLING...”)。
事实上,根本没有记录任何文本。我不知道为什么。
如果我在调用executeSelectQueryAsync 之前使用Thread.Sleep(5000) 并在这5 秒内中止请求,那么TaskCanceledException 会成功引发并捕获。
【问题讨论】:
-
非本地数据库命令对象总是让我紧张。我们可以看看
executeSelectQuery_inner的样子吗? -
与手动记录而不是使用编写良好的记录库一样(即紧张)。由于不保持日志文件打开并准备好写入,您会产生相当大的开销。
-
同意,特别是因为手动记录是问题的原因 - 请参阅下面的答案!
-
是的,是时候选择一个合适的日志库了(这样您就可以在需要时使用它,并且如果您做对了,即使工作正常,也可以保留日志代码,准备好下次有问题要调查)
标签: c# asp.net async-await cancellationtokensource cancellation-token