EntityFramework(6)和async(waitingForActivation)?

时间:2013-07-11 07:12:17

标签: c# entity-framework .net-4.5 async-await entity-framework-6

我已下载EF6(为了使用async

所以我写了这个简单的方法:

  public async Task<List<int>> MyasyncMethod()
      {
          var locations = await MyDumpEntities.AgeGroups.Select(f=>f.endYear).ToListAsync();
          return locations;
       }

   ...Later...


  DumpEntities1 MyDumpEntities = new DumpEntities1();
  var data = MyDumpEntities.AgeGroups.ToListAsync();
  MyasyncMethod().ContinueWith(s => { Response.Write("f"); });
  MyDumpEntities.Dispose();

但我在屏幕上看不到任何内容,当我检查data时,我看到了这一点:

enter image description here

P.S。这是ToListAsync签名 enter image description here

我错过了什么?

3 个答案:

答案 0 :(得分:3)

根据评论以及您遇到问题的行:

var data = MyDumpEntities.AgeGroups.ToListAsync();

data类型是什么? Task<List<AgeGroup>>。这是对的,不是List<AgeGroup>。 因此,您必须将Page_Load标记为异步(如果可能):

public async void Page_Load(object sender, EventArgs e)
{
    using(var MyDumpEntities = new DumpEntities1())
    {
       var data = await MyDumpEntities.AgeGroups.ToListAsync();
    }     
}

或以某种方式等待执行(继续,阻止等待)。

另一件事(如果我错了,别人可能想要纠正),但是因为你正在使用第二次调用的继续,所以我会非常小心处理继续之外的上下文。事实证明,你可以先发制人。在这种特殊情况下,你没有在延续中使用上下文,但它看起来很可疑......

所以我要么

MyasyncMethod().ContinueWith(s => { Response.Write("f"); MyDumpEntities.Dispose();});

或者只使用async

var result = await MyasyncMethod();
Response.Write("f");
MyDumpEntities.Dispose();

并将Async="True"添加到页面指令

答案 1 :(得分:2)

其他人已指出正确的解决方案是使用await,但我没有看到为什么的良好解释。

原始代码错误有两个原因。首先,您使用ContinueWith而不捕获ASP.NET应用程序中的上下文,因此continuation(Response.Write调用)没有请求上下文,因此没有写入的响应。< / p>

await通过捕获await之前的上下文并使用它来恢复方法的其余部分来为您解决这个问题;在这种情况下,它将捕获表示当前请求/响应的AspNetSynchronizationContext

另一个原因是异步代码将同时运行。因此,MyasyncMethod将开始执行,到达其await,并将未完成的任务返回Page_LoadPage_Load然后为该任务附加一个继续,继续执行,处理上下文。因此,在ToListAsync请求仍在运行时,可以处理上下文。

await也为您解决了这个问题,因为它会“暂停”Page_Load方法,直到MyasyncMethod完成。

最后一点,在ASP.NET中使用async时还应考虑以下几点:

  1. 您必须以.NET 4.5为目标。请勿使用Microsoft.Bcl.Async
  2. 您必须将targetFramework设置为4.5,UseTaskFriendlySynchronizationContext设置为true。
  3. (仅限WebForms)将Page.Async设置为true。
  4. 考虑使用RegisterAsyncTask代替await。我通常更喜欢await,因为不同的方法有更多的关注点分离,但ASP.NET团队更喜欢RegisterAsyncTask因为PreRender之后只有一个“同步”点,运行时等待所有要完成的操作。 See this article for how to use RegisterAsyncTask.
  5. 构建您自己的请求超时。异步ASP.NET请求不会自动使用内置于同步ASP.NET请求的正常超时。有两种选择:
    • 使用HttpRequest.TimedOut取消令牌。
    • (仅限WebForms / RegisterAsyncTask)您可以通过设置Page.AsyncTimeout并使用async方法获取CancellationToken来添加异步超时。

答案 2 :(得分:1)

ToListAsync返回Task。将Page_Load标记为异步,然后您可以在其中使用等待。

粗略规则:如果某些内容返回任务(方法名称中包含“Async”),则必须等待它。

此外,使用async / await时,您不必使用ContinueWith。等待您自己的方法并将Write调用放在下一行。

DumpEntities1 MyDumpEntities = new DumpEntities1();
var data = await MyDumpEntities.AgeGroups.ToListAsync();
var dataFromMyMethod = await MyasyncMethod()
Response.Write("f");
MyDumpEntities.Dispose();

并将Async="True"添加到页面指令