[英]cancel async task using cancellationtoken
I would like the users of a web application to be able to cancel long running SQL queries on the server side (by using xhr.abort()
method) 我希望Web应用程序的用户能够取消服务器端长期运行的SQL查询(通过使用xhr.abort()
方法)
I'm using the Response.ClientDisconnectedToken
to catch on the server side the event of the canceling of a request by the user (from here: https://stackoverflow.com/a/17713153/8790102 ) 我正在使用Response.ClientDisconnectedToken
在服务器端捕获用户取消请求的事件(来自此处: https : //stackoverflow.com/a/17713153/8790102 )
The SQL query routine is done in an async
method (from here: https://stackoverflow.com/a/24834029/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;
}
My problem is that the method registered in canceltk.Register()
is not called when aborting the request (the corresponding text "CANCELLING..." is not logged). 我的问题是中止请求时,不会调用在canceltk.Register()
注册的方法canceltk.Register()
未记录相应的文本“ CANCELLING ...”)。
In fact, no text is logged at all. 实际上,根本没有记录任何文本。 I have no idea why. 我不知道为什么。
If I use a Thread.Sleep(5000)
before calling executeSelectQueryAsync
and abort the request during these 5 seconds, then the TaskCanceledException
is successfully raised and caught. 如果在调用executeSelectQueryAsync
之前使用Thread.Sleep(5000)
并在这5秒钟内中止请求,则TaskCanceledException
被成功引发并捕获。
Task.Run
schedules the execution of that code on a thread pool thread which is not controlled by AS.NET's synchronization context. Task.Run
计划在不受AS.NET同步上下文控制的线程池线程上执行该代码。 That's why HttpContext.Current
is null. 这就是HttpContext.Current
为null的原因。
Besides that, in this context, Task.Run
causes the execution of the request to be transferred to another thread pool thread, the request handling thread (another thread pool thread) is returned to the pool and when Task.Run
finishes execution that thread is returned to the thread pool thread and another one is retrieved and populated with request handling data. 除此之外,在这种情况下, Task.Run
导致将请求的执行转移到另一个线程池线程,请求处理线程(另一个线程池线程)返回到池中,并且当Task.Run
完成执行时,该线程为返回到线程池线程,并检索另一个线程并填充请求处理数据。 You just used more resources for no benefit. 您只是使用了更多资源而没有收益。 Quite the contrary. 恰恰相反。
Code that escapes the ASP.NET context should not rely on it. 转义ASP.NET上下文的代码不应依赖它。
Doesn't the Oracle provider support asynchronous operations? Oracle提供程序不支持异步操作吗?
The method was in fact well called, but System.Web.HttpContext.Current
then had a null value, causing a Exception not caught. 该方法实际上被很好地调用,但是System.Web.HttpContext.Current
然后具有空值,导致未捕获到异常。
By replacing with System.Web.Hosting.HostingEnvironment.MapPath
, the code is working successfully. 通过替换为System.Web.Hosting.HostingEnvironment.MapPath
,代码可以成功运行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.