加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 当我用linq键入时运行任务(如果仍在运行则取消上一个任务)

发布时间:2020-12-15 22:07:01 所属栏目:百科 来源:网络整理
导读:我想创建一个在我键入时使用 linq搜索的任务,如果用户键入另一个字符,它应该取消任务并重新创建搜索,我有以下代码: private Task SearchChannels;private CancellationTokenSource cancelSearch;public void PopulateChannels(string newValue){ IsSearchin
我想创建一个在我键入时使用 linq搜索的任务,如果用户键入另一个字符,它应该取消任务并重新创建搜索,我有以下代码:

private Task SearchChannels;
private CancellationTokenSource cancelSearch;

public void PopulateChannels(string newValue)
{
    IsSearchingChannels = true; //This just shows a progressbar
    if (SearchChannels != null && cancelSearch!= null)
        if (SearchChannels.Status == TaskStatus.Running || 
            SearchChannels.Status == TaskStatus.WaitingToRun || 
            SearchChannels.Status == TaskStatus.WaitingForActivation || 
            SearchChannels.Status == TaskStatus.WaitingForChildrenToComplete) 
        {
            cancelSearch.Cancel();
            SearchChannels.Wait();
        }
    cancelSearch = new CancellationTokenSource();
    SearchChannels = new Task(() => Channels = new PagedObservableCollection<Channel>(ContractManager.Channels.Where(x => x.Name.ToLower().StartsWith(newValue)).AsParallel().WithCancellation(cancelSearch.Token).ToList()),cancelSearch.Token); //PagedObservableCollection is just a simple class with a list that keeps all items and an ObservableCollection for current items shown

    SearchChannels.Start();
    SearchChannels.ContinueWith((continuation) => IsSearchingChannels = false); // this just hides the progressbar when done
}

我得到这个例外:

类型’System.OperationCanceledException’的例外
发生在System.Core.dll中但未在用户代码中处理

附加信息:操作已取消.

我是一个有任务和取消的初学者,可以从这里指导我正确的路径吗?我基本上希望Task检查它是否已经运行,取消它,然后使用新值再次运行它(我想使这个“SearchBox”功能类似于visual studio在解决方案资源管理器中的搜索,在您键入时搜索)

解决方法

首先,您需要创建一个IObservable< string>抽象改变控件上的值.执行此操作的“最简单”方法是使用Subject< string>,但很可能是错误的方法.

下面是您应该放入ViewModel的代码.

IDisposable _searchSubscriber =
    _searchString
         .Buffer(TimeSpan.FromMillisecond(300))
         .Select(searchString => 
                Observable.StartAsync(cancelToken => 
                      Search(searchString,cancelToken)
                ).Switch()
         .ObserveOn(new DispatcherScheduler())
         .Subscribe(results => Channels = results);

public Task<List<Channel>> Search(string searchTerm,CancellationToken cancel)
{
    var query = dbContext.Channels.Where(x => x.Name.StartsWith(searchTerm));
    return query.ToListAsync(cancel);
}

private BehaviorSubject<string> _searchString = new BehaviorSubject<string>("");
public string SearchString
{
    get { return _searchString.Value; }
    set { _searchString.OnNext(value); OnPropertyChanged("SearchString"); }
}

Rx.net是一个非常强大的库,当然这意味着它确实有一点学习曲线(尽管事实是这很复杂,因为你的问题很复杂).

让我说出来……

.Buffer(TimeSpan.FromMilliseconds(300))对您的查询进行去抖动,因此它每300毫秒只运行一次查询.

Observable.StartAsync(cancelToken => Search(searchString,cancelToken))为搜索任务创建一个Observable,它将在处理时被取消.

选择(x => …).Switch()仅获取最新的查询结果,并处理最后一个查询.

ObserveOn(…)在使用的调度程序上运行以下命令,确保在使用WPF时使用DispatchScheduler,如果使用Winforms则使用WinformsScheduler.

订阅(结果=> …)对结果做一些事情.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读