【发布时间】:2012-07-07 00:10:09
【问题描述】:
所以我的 UI 上有一个组合框,它在 SelectionChanged 上异步转到 Web 服务,以拉回一些要在 UI 上显示的信息(使用新的 C#5 async/await 关键字)。我要做的是在发送新请求之前取消当前的异步请求;例如,如果用户使用键盘快速循环浏览所有组合框项,则 SelectionChanged 事件可能会在第一个异步请求返回之前触发多次(生成多个异步请求)。
所以我从组合框的 SelectionChanged 事件中调用的异步函数如下所示:
public async Task<Connections> ConnectionsAsync()
{
return await Task.Factory.StartNew(() => Connections, _cancellationTokenSource.Token);
}
Connections 是一个属性,它会触发并访问 Web 服务。所以因为 CancellationTokenSource 一旦被取消就不能重用,我正在考虑这样做:
public async Task<Connections> ConnectionsAsync()
{
_cancellationTokenSource.Cancel();
_cancellationTokenSource = new CancellationTokenSource();
return await Task.Factory.StartNew(() => Connections, _cancellationTokenSource.Token);
}
但问题是,有时我会在没有异步命令运行时调用 Cancel()(例如,第一次调用此函数时);因此,如果我连接任何取消事件处理程序,即使在我发出异步请求之前,它们也会被调用。
有没有办法检查异步请求是否已经在运行?除了我做类似的事情:
public async Task<Connections> ConnectionsAsync()
{
if (_runningAsyncCommand)
_cancellationTokenSource.Cancel();
_cancellationTokenSource = new CancellationTokenSource();
_runningAsyncCommand = true;
return await Task.Factory.StartNew(() => Connections, _cancellationTokenSource.Token);
_runningAsyncCommand = false;
}
我有几个异步函数都使用相同的 CancellationTokenSource,所以我必须在所有这些函数中实现这个“管道”。这是最好的方法吗?或者,还有更好的方法?
另外,如果我公开 _cancellationTokenSource 以便其他类可以使用它注册取消委托,那么将这些委托“转移”到新的 CancellationTokenSource 的最佳方法是什么,因为我每次都在创建一个新委托?
提前致谢!
【问题讨论】:
-
解决了吗?我现在有完全相同的问题。
-
不,它没有解决,但现在回顾我的问题,我认为正确的做法是将 CancellationTokenSource 的令牌作为可选参数(即 public async Task
ConnectionsAsync(CancellationToken token =空))。这样,调用 ConnectionsAsync() 函数的用户负责设置一个新的 CancellationTokenSource 并传入它的 Token。 -
所以在我的示例中,这将发生在我的组合框的 SelectionChanged 事件中;我会在现有的 CancellationTokenSource 上调用 Cancel(),创建一个新的,并将它的 Token 传递给 ConnectionsAsync() 函数。最后,尽管对于我的特定应用程序,我最终没有使用取消。
-
感谢您的更新。我会继续寻找,因为这是我的 UI 应用程序中的常见模式。
标签: c# asynchronous async-await cancellationtokensource