Dynamically search with interrupts,via Tasks C#

I'm working with Db(via SQLite.NET PCL ,not async version). 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.

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 .
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)

2)Initialize timer,then turn on and :

  • if 1 second passed ,then => run my method(query) on Task(similiar to background thread)
  • if 1 second doesn't passed ,then exit from anonymous method.
  • Something like that(similar) or any suggestions.Thanks!

    UPD:
    So to be honest,i tried too much and didnt get a good result
    BTW,my current code(Snippets) :
    1) My 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)

    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).

    Any help will be appreciated,thanks!
    PS Sorry for my eng. skills!


    一种方法是结合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. 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 :

    public void QueryToDB(string filter)
    {
        this.BeginRefresh ();
        ViewModel.isBusy = true;
    
        // do your search
    
        ViewModel.isBusy = false;
        this.EndRefresh ();
    }
    
    链接地址: http://www.djcxy.com/p/87446.html

    上一篇: 问题与Robolectric与新版Google Play服务

    下一篇: 通过任务C#动态搜索中断,