我有一个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
我在这里看起来有用,但代码很难看,应用程序仍然有点迟钝。是否有适当/更好的方法来做到这一点?
答案 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>