与实体框架异步方法和SQL Server Compact阻塞行为 [英] Blocking behaviour with Entity Framework Async methods and SQL Server Compact

查看:95
本文介绍了与实体框架异步方法和SQL Server Compact阻塞行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个MVVM应用程序调用数据服务来获取一些数据绑定。数据服务访问,通过实体框架6.

I have an MVVM app that calls a data service to get some data to bind. The data service accesses a SQL Server Compact (v4.0) database through Entity Framework 6.

数据(目前)需要几秒钟,当所谓的同步这(不奇怪)模块GUI线程。这其中大部分我已经假定为IO约束所以我加了一个等效异步方法以异步方式执行数据加载,使图形用户界面保持响应。然而,当我使用的EF异步方法,它似乎并没有什么差别,GUI线程仍然块,大致相同的时间。

The data (currently) takes a few seconds to be loaded and when called synchronously this (not surprisingly) blocks the GUI thread. Most of this I had assumed to be IO bound so I added an equivalent Async method to execute the data load in an asynchronous fashion to allow the GUI to remain responsive. However when I make use of the EF Async methods, it doesn't appear to make any difference, the GUI thread still blocks, for roughly the same amount of time.

据我所知,使用异步调用将无法工作转移到一个不同的线程,但是我曾以为广大这项活动的进行IO约束。因此,使用EF异步方法应该允许调用(GUI)线程继续做其他的工作,但它不作任何区别。

I understand that using the Async calls will not move the work to a different thread, however I had assumed the majority of this activity to be IO bound. Hence using the EF Async methods should allowing the calling (GUI) thread to continue doing other work, but it is not making any difference.

例如,如果我写的LoadData方法使用EF同步Load方法,则GUI阻塞,直到数据被加载:

For example if I write the LoadData method to use the EF synchronous Load method, then the GUI blocks until the data is loaded:

public ObservableCollection<Data> GetData()
{
    //Do IO bound activity...
    Context.DataTable1.Include(...).Load();

    //for demo purposes, just return some data
    return Context.DataTable1.Local; //(ObservableCollection<Data>)
}

异步方法加载的数据是这样的:

The Async method to load the data looks like this:

public async Task<ObservableCollection<Data>> GetDataAsync()
{
    //Do IO bound activity...
    var task = Context.DataTable1.Include(...).LoadAsync();
    await task;

    //for demo purposes, just return some data
    return Context.DataTable1.Local; //(ObservableCollection<Data>)
}

令人惊讶的(对我来说)我得到相同的结果,它块大致相同的时间长度调用线程(我把秒表就可以了)。

Surprisingly (for me) I get the same result and it blocks the calling thread for roughly the same length of time (I put a stopwatch on it).

我开始思考,除了数据库IO束缚的工作,有可能是导致阻塞CPU密集型活动的某些最低金额。于是,我终于尝试用Task.Run()执行在后台线程的工作:

I started thinking that in addition to the database IO bound work, there may be some minimum amount of CPU bound activity that is causing the blocking. So I finally tried executing the work on a background thread by using Task.Run():

public async Task<ObservableCollection<Data>> GetDataAsync()
{
    //Do IO bound activity...
    Task<ObservableCollection<Competition>> task = Task.Run(async () => 
    { 
        //Do IO bound activity...
        var task = Context.DataTable1.Include(...).LoadAsync();
        await task;

        //for demo purposes, just return some data
        return Context.DataTable1.Local; //(ObservableCollection<Data>)
    });
    var result = await task;
    return result;
}

通过此,在GUI显然不阻止和响应的整个时间。

With this, the GUI obviously doesn't block and is responsive the entire time.

我读过围绕这一切的许多文章,包括岗位<一个href=\"http://stackoverflow.com/questions/16063520/how-do-you-create-a-async-method-in-c-sharp-5\">here和<一个href=\"http://stackoverflow.com/questions/27790468/is-it-possible-to-await-an-io-operation-that-is-not-declared-as-async-if-not-w\">here和博客文章由斯蒂芬·克利里约时,不要(这里)以及何时(这里)使用Task.Run。据我所知,我的最后一个例子上面依然阻挡,它仅仅是阻塞线程池线程。我真的不明白的是,在访问EF异步方法时,为什么它没有出现被提供任何好处?

I've read many articles all around this, including posts here and here and blog posts by Stephen Cleary about when not to (here) and when to (here) use Task.Run. I understand that my last example above is still blocking, it is just blocking a threadpool thread. What I don't understand really is, why when accessing the EF async methods does it not appear to be providing any benefit?

难道说虽然有IO活动正在进行,也有足够的CPU绑定工作,引起堵塞?这当然是采取比50ms的显著不再响应,接近2或3秒来运行所有的查询,所以这种类型的活动可以开始证明使用Task.Run的?

Could it be that whilst there is IO activity going on, there is also sufficient CPU bound work to cause the blocking? It is certainly taking significantly longer than 50ms to respond, closer to 2 or 3 seconds to run all the queries, so this type of activity can start justifying the use of the Task.Run?

或者,我已经写了异步方法不正确,因此为什么它仍然阻挡?

Or, have I written the Async method incorrectly, hence why it is still blocking?

我也想知道是否也许是异步方法为SQL精简供应商EF是出于某种原因,回落至标准的同步调用?

I also wondered if perhaps the Async methods for the SQL Compact provider for EF were for some reason falling back to the standard synchronous calls?

推荐答案

SQL Server精简ADO.NET提供者不提供任何异步的API。但是加载数据不应该采取fewcseconds,除非你是获取行的1000。初始化dbContext.connection对象当您启动应用程序,并留下空,不使用你的应用程序的生命周期。还存在的的DbContext首次初始化的成本。

The SQL Server Compact ADO.NET provider does not provide any Async APIs. But loading data should never take a fewcseconds, unless you are fetching 1000s of rows. Initialize a dbContext.connection object when you start your app, and leave empty and unused for the lifetime of your app. There is also a cost of init of dbContext first time.

这篇关于与实体框架异步方法和SQL Server Compact阻塞行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆