简体   繁体   中英

EF 5: How to cancel a longrunning query in a async Task

In my application I have multiple tabs, displaying data from a database with Entity Framework 5.

When I switch between the tabs I start auto loading the data via a Task, because I don't want the GUI to become unresponsive (this task takes about 5-10 seconds):

public async void LoadData()
{
    [...]

    await Task.Run(
        () =>
            {
                Measurements = DataContext.Measurements
                                  .Where(m => m.MeasureDate = DateTime.Today)
                                  .ToList();
            });

    [...]
}

But while the task runs the user still can change to another tab, and if he does that I would like to cancel the EF query and/or the Task.

What would be the best way to accomplish this?

In EF5, there is no way to cancel the queries since it doesn't accept CancellationToken . You can read more about this here: entity framework cancel long running query

However, EF6 does support it.

It has async version of all methods. So ToList() could instead be ToListAsync() for long running queries and it does have support for CancellationToken .

// ***Declare a System.Threading.CancellationTokenSource.
CancellationTokenSource cts;
public async void LoadData()
{
   // ***Instantiate the CancellationTokenSource.
    cts = new CancellationTokenSource();
    await Task.Run(
        () =>
            {
                Measurements = DataContext.Measurements
                                  .Where(m => m.MeasureDate = DateTime.Today)
                                  .ToList();
            }, cts);

}

    //I dont know what front end you using but in WPF for example on the tab event
    <TabControl SelectionChanged="OnSelectionChanged" ... />

private void OnSelectionChanged(Object sender, SelectionChangedEventArgs args)
{
    TabItem item = sender as TabItem; //The sender is a type of TabItem...

    if (item != null)
    {
         if (cts != null)
         {
            //This cancels the current long Running task.
            cts.Cancel();

            //call for next tab with filter LoadData(filter);
         }
    }
}

My personal view is. The best way to go about doing this is to load all the data for your tabs upfront if you can. And then render the view. So when you click between tabs the data is already loaded. Plus the cost of calling the database only affects you once. Instead of roundtrips to the database everytime you click on a tab.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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