[英]C# : Cancelling MySqlCommand using CancellationToken giving NULLReferenceException
I was trying to cancel a MySqlCommand
using a CancellationToken
.我试图使用
CancellationToken
取消MySqlCommand
。 The query executes successfully when cancellation is not requested.当未请求取消时,查询成功执行。
public async Task<int> ExecuteNonQueryAsync(string connectionString, string query,
CancellationToken cancellationToken)
{
int affectedRowsCount = 0;
await Task.Run(() =>
{
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
using (MySqlCommand command = new MySqlCommand())
{
connection.Open();
command.Connection = connection;
cancellationToken.Register(() => command.Cancel());
command.CommandText = query;
command.CommandTimeout = 0;
affectedRowsCount = command.ExecuteNonQuery();
connection.Close();
}
}
});
return affectedRowsCount;
}
But when cancellation is requested it is producing NullReferenceException.但是当请求取消时,它会产生 NullReferenceException。 Can't figure out what is NULL.
无法弄清楚什么是NULL。
I am calling the above method by我通过调用上述方法
deletedRowsInLastIteration = await
mySqlHelperService.ExecuteNonQueryAsync(
connectionString,
query,
cancellationToken);
if I try如果我尝试
cancellationToken.ThrowIfCancellationRequested();
before calling the ExecuteNonQueryAsync()
method, it works.在调用
ExecuteNonQueryAsync()
方法之前,它可以工作。 But the cancel of MySqlCommand is not working.但是取消 MySqlCommand 不起作用。
This is the stack trace这是堆栈跟踪
System.NullReferenceException HResult=0x80004003 Message=Object reference not set to an instance of an object.
System.NullReferenceException HResult=0x80004003 消息=未将对象引用设置为对象的实例。 Source=MySql.Data
源=MySql.Data
StackTrace: at MySql.Data.MySqlClient.MySqlConnection.CancelQuery(Int32 timeout)StackTrace:在 MySql.Data.MySqlClient.MySqlConnection.CancelQuery(Int32 超时)
at MySql.Data.MySqlClient.MySqlCommand.Cancel() at ProjectName.Common.MySqlHelperService.<>c__DisplayClass1_1.b__1() in C:\\Users\\username\\source\\repos\\ProjectName\\Applications\\ProjectName.Common\\MySqlHelperService.cs:line 55 at System.Threading.CancellationToken.ActionToActionObjShunt(Object obj) at System.Threading.CancellationCallbackInfo.ExecutionContextCallback(Object obj) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.CancellationCallbackInfo.ExecuteCallback() at System.Threading.CancellationTokenSource.CancellationCallbackCoreWork(CancellationCallbackCoreWorkArguments args) at System.Threading.CancellationTo在 MySql.Data.MySqlClient.MySqlCommand.Cancel() 在 ProjectName.Common.MySqlHelperService.<>c__DisplayClass1_1.b__1() 在 C:\\Users\\username\\source\\repos\\ProjectName\\Applications\\ProjectName.Common\\MySqlHelperService.cs:第 55 行在 System.Threading.CancellationToken.ActionToActionObjShunt(Object obj) at System.Threading.CancellationCallbackInfo.ExecutionContextCallback(Object obj) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System。 Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.CancellationCallbackInfo.ExecuteCallback() at System.Threading .CancellationTokenSource.CancellationCallbackCoreWork(CancellationCallbackCoreWorkArguments args) 在 System.Threading.CancellationTo kenSource.ExecuteCallbackHandlers(Boolean throwOnFirstException)
kenSource.ExecuteCallbackHandlers(Boolean throwOnFirstException)
You shouldn't use Task.Run
to convert synchronous methods to asynchronous ones.您不应该使用
Task.Run
将同步方法转换为异步方法。 At best, this wastes a thread just waiting for some IO operation to complete.充其量,这浪费了一个线程只是在等待一些 IO 操作完成。
MySqlCommand
has an ExecuteNonQueryAsync
method that accepts a cancellation token. MySqlCommand
有一个ExecuteNonQueryAsync
方法,它接受取消标记。 MySqlConnection
itself has an OpenAsync
method. MySqlConnection
本身有一个OpenAsync
方法。 You should change your code to :您应该将代码更改为:
public async Task<int> ExecuteNonQueryAsync(string connectionString, string query,
CancellationToken cancellationToken)
{
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
using (MySqlCommand command = new MySqlCommand(query,connection))
{
await connection.OpenAsync();
command.CommandTimeout = 0;
var affectedRowsCount = await command.ExecuteNonQuery(cancellationToken);
}
}
return affectedRowsCount;
}
How are you creating your cancellation Token and what is his value?你是如何创建你的取消令牌的,他的价值是什么?
Also here is a solution how to cancel a sql command with a cancellation token这里还有一个解决方案如何使用取消令牌取消 sql 命令
private CancellationTokenSource cts;
private async void TestSqlServerCancelSprocExecution()
{
cts = new CancellationTokenSource();
try
{
await Task.Run(() =>
{
using (SqlConnection conn = new SqlConnection("connStr"))
{
conn.InfoMessage += conn_InfoMessage;
conn.FireInfoMessageEventOnUserErrors = true;
conn.Open();
var cmd = conn.CreateCommand();
cts.Token.Register(() => cmd.Cancel());
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "dbo.[CancelSprocTest]";
cmd.ExecuteNonQuery();
}
});
}
catch (SqlException)
{
// sproc was cancelled
}
} }
The code above is from this question, which had kinda the same problem, that the cancellation token won't cancel the sql command. 上面的代码来自这个问题,它有同样的问题,取消令牌不会取消 sql 命令。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.