Staeff
Staeff

Reputation: 5084

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?

Upvotes: 6

Views: 2131

Answers (2)

TCM
TCM

Reputation: 16900

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.

Upvotes: 9

dean oliver
dean oliver

Reputation: 945

// ***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.

Upvotes: 0

Related Questions