使用一次性对象的回调取消操作的正确方法是什么?

What's the correct way to cancel an operation with a callback on a disposable object?

我正在努力将控制器移植到异步。部分工作涉及使用在请求生命周期内有效的取消令牌,等待对一次性对象执行异步、可取消的操作。在这种特殊情况下,它是 WebClient.UploadStringTaskAsync(Uri uri, string data).

我知道使用 cancellationToken.Register(() => webClient.CancelAsync()) 取消 WebClient 异步操作的正确方法。但是,WebClient 是在 using 语句中创建的,因此它被放置在块的末尾。因此,从回调中调用 webClient.CancelAsync() 会导致 "Access to disposed closure" 警告。我发现 CancellationToken.Register(Action callback) 导致 CancellationTokenRegistration 对象实现 IDisposable 并在处置时取消注册回调。最后,我的代码如下所示:

using (var webClient = new WebClient())
using (cancellationToken.Register(() => webClient.CancelAsync())
{
     await webClient.UploadStringTaskAsync(uri, data);
}

// cancellationToken can be cancelled later.

我已经制作了一个控制台应用程序来展示具有相同精神的代码的工作原理,并且在处置一次性对象和令牌注册后取消令牌不会导致调用一次性对象的回调。不过我想确定一下:这是正确且安全的吗?

编辑: 我想我应该稍微改一下我的问题。使用取消令牌取消一次性对象上的异步操作的标准解决方案是什么,该操作仅支持通过注册回调进行取消?

Is this correct and safe?

是的。

What's the standard solution for using a cancellation token to cancel an async operation on a disposable object where the operation only supports cancellation through registering a callback?

理想情况下,操作直接采用 CancellationToken。在这种情况下,您已有的方法就可以了。