4

所以我的 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 的最佳方法是什么,因为我每次都创建一个新委托?

提前致谢!

4

1 回答 1

2

看起来就像是天作之合的反应式扩展。在创建任务之前从 Combobox 观察事件时定义必须经过的节流时间(比如 300 毫秒)

订阅 TextBox 更改事件的代码片段,但您会明白:

var input (from evt in Observable.FromEvent<EventArgs>(txt, "TextChanged")
select ((TextBox)evt.Sender).Text)
.Throttle(TimeSpan.FromSeconds(1))
.DistinctUntilChanged();

using (input.Subscribe(inp => Console.WriteLine("You wrote: " + inp)))
{
  // Do stuff
}
于 2012-07-07T16:57:54.783 回答