我试图使用 CancellationToken
取消 MySqlCommand
。当未请求取消时,查询执行成功。
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;
}
但是当请求取消时,它会产生 NullReferenceException。 无法弄清楚什么是 NULL。
我通过以下方式调用上述方法
deletedRowsInLastIteration = await
mySqlHelperService.ExecuteNonQueryAsync(
connectionString,
query,
cancellationToken);
如果我尝试
cancellationToken.ThrowIfCancellationRequested();
在调用ExecuteNonQueryAsync()
方法之前,它可以工作。但是MySqlCommand的取消不起作用。
这是堆栈跟踪
System.NullReferenceException HResult=0x80004003 Message=Object reference not set to an instance of an object. Source=MySql.Data
StackTrace: at MySql.Data.MySqlClient.MySqlConnection.CancelQuery(Int32 timeout)
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.CancellationTokenSource.ExecuteCallbackHandlers(Boolean throwOnFirstException)
最佳答案
您不应使用Task.Run
将同步方法转换为异步方法。充其量,这会浪费一个线程来等待某些 IO 操作完成。
MySqlCommand
有一个接受取消 token 的 ExecuteNonQueryAsync
方法。 MySqlConnection
本身有一个 OpenAsync
方法。您应该将代码更改为:
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;
}
关于C# : Cancelling MySqlCommand using CancellationToken giving NULLReferenceException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59404269/