Skip to content

Commit 4aa0b27

Browse files
committed
Lazily create CancelAction only when needed.
1 parent 9c8a3dc commit 4aa0b27

File tree

4 files changed

+21
-6
lines changed

4 files changed

+21
-6
lines changed

src/MySqlConnector/MySqlClient/CommandExecutors/TextCommandExecutor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public virtual async Task<DbDataReader> ExecuteReaderAsync(string commandText, M
5151
CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken)
5252
{
5353
cancellationToken.ThrowIfCancellationRequested();
54-
using (cancellationToken.Register(m_command.CancelAction))
54+
using (m_command.RegisterCancel(cancellationToken))
5555
{
5656
m_command.Connection.Session.StartQuerying(m_command);
5757
m_command.LastInsertedId = -1;

src/MySqlConnector/MySqlClient/MySqlCommand.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ public MySqlCommand(string commandText, MySqlConnection connection, MySqlTransac
3737
DbTransaction = transaction;
3838
m_parameterCollection = new MySqlParameterCollection();
3939
CommandType = CommandType.Text;
40-
CancelAction = Cancel;
4140
}
4241

4342
public new MySqlParameterCollection Parameters
@@ -51,8 +50,6 @@ public MySqlCommand(string commandText, MySqlConnection connection, MySqlTransac
5150

5251
public override void Cancel() => Connection.Cancel(this);
5352

54-
internal Action CancelAction { get; private set; }
55-
5653
public override int ExecuteNonQuery() =>
5754
ExecuteNonQueryAsync(IOBehavior.Synchronous, CancellationToken.None).GetAwaiter().GetResult();
5855

@@ -159,6 +156,23 @@ protected override void Dispose(bool disposing)
159156

160157
internal new MySqlConnection Connection => (MySqlConnection) DbConnection;
161158

159+
/// <summary>
160+
/// Registers <see cref="Cancel"/> as a callback with <paramref name="token"/> if cancellation is supported.
161+
/// </summary>
162+
/// <param name="token">The <see cref="CancellationToken"/>.</param>
163+
/// <returns>An object that must be disposed to revoke the cancellation registration.</returns>
164+
/// <remarks>This method is more efficient than calling <code>token.Register(Command.Cancel)</code> because it avoids
165+
/// unnecessary allocations.</remarks>
166+
internal IDisposable RegisterCancel(CancellationToken token)
167+
{
168+
if (!token.CanBeCanceled)
169+
return null;
170+
171+
if (m_cancelAction == null)
172+
m_cancelAction = Cancel;
173+
return token.Register(m_cancelAction);
174+
}
175+
162176
private void VerifyNotDisposed()
163177
{
164178
if (m_parameterCollection == null)
@@ -183,5 +197,6 @@ private void VerifyValid()
183197
MySqlParameterCollection m_parameterCollection;
184198
CommandType m_commandType;
185199
ICommandExecutor m_commandExecutor;
200+
Action m_cancelAction;
186201
}
187202
}

src/MySqlConnector/MySqlClient/MySqlDataReader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ private ValueTask<ResultSet> ScanResultSetAsync(IOBehavior ioBehavior, ResultSet
108108

109109
private async Task<ResultSet> ScanResultSetAsyncAwaited(IOBehavior ioBehavior, ResultSet resultSet, CancellationToken cancellationToken)
110110
{
111-
using (cancellationToken.Register(Command.CancelAction))
111+
using (Command.RegisterCancel(cancellationToken))
112112
{
113113
try
114114
{

src/MySqlConnector/MySqlClient/Results/ResultSet.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ private ValueTask<Row> ScanRowAsync(IOBehavior ioBehavior, Row row, Cancellation
162162
if (BufferState == ResultSetState.HasMoreData || BufferState == ResultSetState.NoMoreData || BufferState == ResultSetState.None)
163163
return new ValueTask<Row>((Row)null);
164164

165-
using (cancellationToken.Register(Command.CancelAction))
165+
using (Command.RegisterCancel(cancellationToken))
166166
{
167167
var payloadValueTask = Session.ReceiveReplyAsync(ioBehavior, CancellationToken.None);
168168
return payloadValueTask.IsCompletedSuccessfully

0 commit comments

Comments
 (0)