简体   繁体   English

通过任务C#动态搜索中断

[英]Dynamically search with interrupts,via Tasks C#

I'm working with Db(via SQLite.NET PCL ,not async version). 我正在使用Db(通过SQLite.NET PCL ,而不是异步版本)。 At current moment i have a listview with some data(taken from db),also i got a searchbar/entry(its nvm),where user can input some values and then,via LINQ i'm going to make a query and update SourceItems of my List. 在目前我有一个列表视图与一些数据(取自数据库),我也有一个搜索栏/条目(其nvm),用户可以输入一些值然后,通过LINQ我将进行查询和更新SourceItems我的清单。

So the problems comes with performance,because my DB got million records and simple LINQ query working very slow.In other words,when user enter too fast some data,application gets huge lags and sometimes can Crash . 所以问题来自于性能,因为我的数据库有百万条记录和简单的LINQ查询工作非常慢。换句话说,当用户输入的数据太快时,应用程序会有很大的滞后,有时会崩溃
To resolve this problem,some things come in my mind(theoretically solution): 为了解决这个问题,我想到了一些事情(理论上的解决方案):

1)Need to put method(which i make query into db) on Task(to unlock my main UI thread) 1)需要在任务上放置方法(我对db进行查询)(解锁我的主UI线程)

2)Initialize timer,then turn on and : 2)初始化计时器,然后打开并:

  • if 1 second passed ,then => run my method(query) on Task(similiar to background thread) 如果1秒过去 ,那么=>在任务上运行我的方法(查询)(类似于后台线程)
  • if 1 second doesn't passed ,then exit from anonymous method. 如果1秒没有通过 ,则退出匿名方法。

Something like that(similar) or any suggestions.Thanks! 类似的东西(类似)或任何建议。谢谢!

UPD: UPD:
So to be honest,i tried too much and didnt get a good result 所以说实话,我尝试了太多,并没有得到一个好结果
BTW ,my current code(Snippets) : BTW ,我目前的代码(Snippets):
1) My SearchMethod 1)我的SearchMethod

public void QueryToDB(string filter)
        {
            this.BeginRefresh ();

            if (string.IsNullOrWhiteSpace (filter))
            {
                this.ItemsSource = SourceData.Select(x => x.name); // Source data is my default List of items
            }
            else 
            {
                var t = App.DB_Instance.FilterWords<Words>(filter); //FilterWords it's a method,where i make direct requests to the database 
                this.ItemsSource = t.Select(x => x.name); 
            }
            this.EndRefresh ();
        }

2)Searchbar.TextChanged (anonymous method) 2)Searchbar.TextChanged(匿名方法)

searchBar.TextChanged +=async (sender, e) => 
                {
                    ViewModel.isBusy = true;  //also i got a indicator,to show progress,while query working
                    await Task.Run(()=> //my background,works fine
                    {
                        listview.QueryToDB(searchBar.Text);
                    });
                    ViewModel.isBusy = false; // after method is finished,indicator turn off

                };

The main problem is how to implement this part(with these case's),where 1 second passed and only then i'm going to make query to update my sourceItems of list(everytime,when user inputs some value into searchbar,this trigger(timer) must refresh again to zero). 主要的问题是如何实现这个部分(使用这些情况),其中1秒传递,然后我将进行查询以更新我的listItems列表(每次,当用户输入一些值到搜索栏,这个触发器(计时器) )必须再次刷新为零)。

Any help will be appreciated,thanks! 任何帮助将不胜感激,谢谢!
PS Sorry for my eng. PS对不起我的工程师。 skills! 技能!

One way to do it is to combine async Task.Run and CancellationTokenSource : 一种方法是组合async Task.RunCancellationTokenSource

CancellationTokenSource cancellationTokenSource;

searchView.TextChanged += async (sender, e) => 
{
    if (cancellationTokenSource != null) cancellationTokenSource.Cancel();
    cancellationTokenSource = new CancellationTokenSource();
    var cancellationToken = cancellationTokenSource.Token;

    var searchBar = (sender as SearchBar);
    if (searchBar != null)
    {
        string searchText = searchBar.Text;
        try
        {
            await Task.Delay(650, cancellationToken);

            if (cancellationToken.IsCancellationRequested) return;

            var searchResults = await Task.Run(() => 
            {
                return ViewModel.Search(searchText);
            });

            if (cancellationToken.IsCancellationRequested) return;

            ViewModel.YouItems.Repopulate(searchResults);
        }
        catch (OperationCanceledException)
        {
            // Expected
        }
        catch (Exception ex)
        {
            Logger.Error(ex);
        }
    }
};

You want to wait before actually performing your search. 您想在实际执行搜索之前等待 Killing a search task in midway can cause undefined behavior. 在中途杀死搜索任务可能会导致未定义的行为。

You want to save the current search filter and compared it again 1 second later. 您想要保存当前搜索过滤器,并在1秒后再次对其进行比较。 If that hasn't changed, do the search. 如果没有改变,请进行搜索。 Otherwise, abort : 否则,中止:

searchBar.TextChanged += async (sender, e) => 
{
    var filter = searchBar.Text;
    await Task.Run(() =>
    {
        Thread.Sleep(1000);
        if (filter == searchBar.Text)
            listview.QueryToDB(searchBar.Text);
    });
};

As to keep the view model updated, move your isBusy assignments inside QueryToDB because that is when your view model is truly busy : 以保持视图模型更新,将您isBusy分配内部QueryToDB ,因为这是当你的视图模型是真正的忙:

public void QueryToDB(string filter)
{
    this.BeginRefresh ();
    ViewModel.isBusy = true;

    // do your search

    ViewModel.isBusy = false;
    this.EndRefresh ();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM