【问题标题】:cancel and start a new async task based on navigation根据导航取消并启动新的异步任务
【发布时间】:2015-04-08 06:52:55
【问题描述】:

我有一个 WPF 表单,它的屏幕被分成 2 个部分作为主详细信息表单。上面的部分是主人,它显示了一个数据网格中的一堆记录,这些记录是数据绑定到一个collectionviewsource。 每当用户单击一行时,表单的底部都是通过对 collectionviewsource.current_changed 事件做出反应而构建的。 在那里,我正在取消任何未决的异步操作,并开始一个新的操作。 代码是这样的:

if (_tokenSource != null) //_tokenSource is an instance variable of the class that implements current_changed
{
    try
    {
        _tokenSource.Cancel(); //needed because _tokenSource might be disposed already. Ugly.
    }
    catch (Exception Ex)
    {
    }
}

using (_tokenSource = new CancellationTokenSource())
{
    try
    {
        _unitOfWork = await loadRelatieAsync(relatieId, _tokenSource.Token); // this is just currently an await Task.Delay(5000,token).ConfigureAwait(true); return null;
    }
    catch (Exception Ex)
    {
    }
}
//_tokenSource = null; can’t do this, it would lead to several operations not being cancelled

我在这里的东西似乎可以工作,但是代码很难看,应用程序仍然有点迟钝。有没有合适/更好的方法来做到这一点?

【问题讨论】:

    标签: wpf mvvm async-await collectionviewsource


    【解决方案1】:

    我通常不会费心处理CancellationTokenSource。如果你只是覆盖它而不释放它,代码会更干净:

    if (_tokenSource != null)
      _tokenSource.Cancel();
    
    _tokenSource = new CancellationTokenSource();
    try
    {
      _unitOfWork = await loadRelatieAsync(relatieId, _tokenSource.Token);
      return null;
    }
    catch (OperationCanceledException ex)
    {
    }
    

    关于“迟缓”,我猜测可能是由于用户快速更改了主视图中的选定项目?如果是这样,您可能希望在开始新操作之前引入一个小的(例如 100 毫秒)延迟。这可以使用async 代码来完成:

    if (_tokenSource != null)
    {
      _tokenSource.Cancel();
      _tokenSource = null;
    }
    
    var currentItem = _whateverView.CurrentItem;
    await Task.Delay(TimeSpan.FromMilliseconds(100));
    if (currentItem != _whateverView.CurrentItem)
      return null;
    
    _tokenSource = new CancellationTokenSource();
    try
    {
      _unitOfWork = await loadRelatieAsync(relatieId, _tokenSource.Token);
      return null;
    }
    catch (OperationCanceledException ex)
    {
    }
    

    虽然我必须说,如果您正在执行大量“基于时间”的操作(例如“将此操作延迟一段时间”或“根据此时间窗口限制这些事件”),那么更多自然的方法是Reactive Extensions

    【讨论】:

    • 指出,即使等待 100 毫秒也有助于其他缓慢的行为。我将不得不深入研究响应式扩展,看看它们如何适合这里。
    猜你喜欢
    • 1970-01-01
    • 2018-02-22
    • 2015-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多