SignalR クライアントが .NET 11 Preview 6 でついに実行中のハブメソッドをキャンセルできます
InvokeAsync に渡す CancellationToken のキャンセルがサーバーに届き、ハブメソッドをキャンセルするようになりました。2019 年から開いていた SignalR の要望が解決します。
.NET 11 Preview 6 は 2026-07-15 にリリースされ、SignalR で最も長く残っていた機能要望の 1 つを解決します。Issue #11542「Possibility to cancel long running hub method from client」は 2019 年から開いていました。PR #64098 でついに配線され、.NET クライアントで InvokeAsync に渡す CancellationToken が実際にサーバーに届き、ハブメソッドをキャンセルするようになりました。
これまであなたを欺いていたトークン
Preview 6 より前でも、.NET の SignalR クライアントは InvokeAsync で CancellationToken を受け取っていました。ただ、多くの人が想定した動作はしていませんでした。キャンセルするとクライアントが結果を待つのを止めますが、サーバー側のハブメソッドは最後まで実行を続けていました。サーバーに「止めてください、呼び出し元は離れました」と伝える手段がなかったのです。ストリーミング呼び出しは CancelInvocation メッセージを送信していましたが、通常のリクエスト・レスポンス呼び出しは送信していませんでした。
そのギャップはなくなりました。InvokeAsync に渡したトークンをキャンセルすると、クライアントは CancelInvocationMessage をサーバーに送信し、サーバーは対応する呼び出しを見つけてキャンセルします。
配線のしかた
サーバーでは、ハブメソッドに CancellationToken パラメーターを宣言します。SignalR がそれを合成引数として埋めるため、クライアントは決してそれを送信しません。
public class ReportHub : Hub
{
public async Task<string> BuildReport(int rows, CancellationToken cancellationToken)
{
for (var i = 0; i < rows; i++)
{
cancellationToken.ThrowIfCancellationRequested();
await Task.Delay(50, cancellationToken); // real work here
}
return "done";
}
}
Preview 6 までは、ストリーミングでないハブメソッドの CancellationToken パラメーターは無視されていました。フレームワークはストリーミングメソッドに対してのみそれを合成していたためです。今では HubMethodDescriptor がどこでもそれを許可します。
クライアントでは、トークンを渡し、結果が不要になったらキャンセルします。
using var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(2));
try
{
var result = await connection.InvokeAsync<string>(
"BuildReport", 100_000, cts.Token);
}
catch (OperationCanceledException)
{
// The server's token fired too, so the hub method stopped.
}
内部で起きていること
DefaultHubDispatcher は、各呼び出しの CancellationTokenSource を呼び出し id をキーとして ActiveRequestCancellationSources に登録します。CancelInvocationMessage が届くと、そのソースを探して Cancel() を呼び出し、ハブメソッドが監視しているトークンが発火します。これはストリーミング呼び出しがすでに使っていたのと同じレジストリで、今は通常の呼び出しと共有されています。
覚えておくべき点が 2 つあります。キャンセルは協調的です。ハブメソッドがトークンを一度も確認せず、実行する非同期呼び出しに転送もしなければ、何も止まりません。そして、これはプレビューであるため、.NET 11 が 2026 年 11 月にリリースされるまでに動作はまだ変わる可能性があります。
同じ Preview 6 では自動 CSRF 保護も有効化されたので、テストするのに良いリリースです。詳細はすべて ASP.NET Core Preview 6 のリリースノートにあります。ユーザーを欺くだけの「キャンセル」ボタンをこれまでに作ったことがあるなら、これはそれを誠実にするリリースです。
Comments
Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.