根据导航取消并启动新的异步任务

时间:2015-02-08 13:25:56

标签: wpf mvvm async-await collectionviewsource

我有一个WPF表单,该屏幕分为两部分作为主要详细信息表单。上面的部分是master,它在datagrid中显示了一堆记录,这些记录是到collectionviewsource的数据绑定。 只要用户单击一行,表单的底部就会通过对collectionsviewsource.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

我在这里看起来有用,但代码很难看,应用程序仍然有点迟钝。是否有适当/更好的方法来做到这一点?

1 个答案:

答案 0 :(得分:3)

我一般不打扰处理CancellationTokenSource。如果您只是覆盖它而不进行处理,则代码更清晰:

if (_tokenSource != null)
  _tokenSource.Cancel();

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

关于"迟缓",我猜测可能是因为用户在主视图中快速更改了所选项目?如果是这样,您可能希望在开始新操作之前引入一个小的(例如,100ms)延迟。这可以使用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)
{
}

虽然我必须说,如果你做了很多&#34;基于时间的&#34;操作(例如&#34;延迟此操作一段时间&#34;或者&#34;根据此时间窗口限制这些事件&#34;),然后更自然的方法是Reactive Extensions。< / p>