简体   繁体   English

EF 5:如何在异步任务中取消长运行查询

[英]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. 在我的应用程序中,我有多个选项卡,使用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): 当我在选项卡之间切换时,我开始通过任务自动加载数据,因为我不希望GUI变得无响应(此任务大约需要5-10秒):

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. 但是当任务运行时,用户仍然可以更改为另一个选项卡,如果他这样做,我想取消EF查询和/或任务。

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 . 在EF5中,无法取消查询,因为它不接受CancellationToken You can read more about this here: entity framework cancel long running query 你可以在这里阅读更多相关内容: 实体框架取消长时间运行的查询

However, EF6 does support it. 但是,EF6确实支持它。

It has async version of all methods. 它具有所有方法的异步版本。 So ToList() could instead be ToListAsync() for long running queries and it does have support for CancellationToken . 因此,对于长时间运行的查询, ToList()可能是ToListAsync() ,它确实支持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. 每次单击选项卡时,而不是往返数据库。

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

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