首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EntityFramework (6)和异步( waitingForActivation)?

EntityFramework (6)和异步( waitingForActivation)?
EN

Stack Overflow用户
提问于 2013-07-11 07:12:16
回答 3查看 4.5K关注 0票数 1

我下载了EF6 (为了使用async)

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

代码语言:javascript
复制
  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时,我看到了以下内容:

附注:这是ToListAsync签名

我错过了什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-07-11 07:25:38

以评论和你有问题的行为基础:

代码语言:javascript
复制
var data = MyDumpEntities.AgeGroups.ToListAsync();

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

代码语言:javascript
复制
public async void Page_Load(object sender, EventArgs e)
{
    using(var MyDumpEntities = new DumpEntities1())
    {
       var data = await MyDumpEntities.AgeGroups.ToListAsync();
    }     
}

或者以某种方式等待执行(继续、阻塞等待)。

另一件事(如果我错了,其他人可能想纠正这一点),但是由于您在第二个调用中使用了延续,所以我会非常小心地处理延续之外的上下文。结果可能是您预先处理上下文。在这种情况下,您没有在继续中使用上下文,但它看起来很可疑.

所以我要么

代码语言:javascript
复制
MyasyncMethod().ContinueWith(s => { Response.Write("f"); MyDumpEntities.Dispose();});

或者也可以在那里使用async

代码语言:javascript
复制
var result = await MyasyncMethod();
Response.Write("f");
MyDumpEntities.Dispose();

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

票数 3
EN

Stack Overflow用户

发布于 2013-07-11 10:39:22

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

原始代码错误的原因有两个。首先,您在使用ContinueWith时没有捕获ASP.NET应用程序中的上下文,因此延续( Response.Write调用)没有请求上下文,因此没有要写入的响应。

await通过捕获await之前的上下文并使用该上下文恢复方法的其余部分来为您处理这一问题;在本例中,它将捕获表示当前请求/响应的AspNetSynchronizationContext

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

await还为您修复了这个问题,因为它将“暂停”Page_Load方法,直到MyasyncMethod完成为止。

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

  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之后有一个“同步”点,运行时等待所有操作完成。.
  5. 构建您自己的请求超时。异步ASP.NET请求不会自动使用内置于同步ASP.NET请求的正常超时。有两个选项:
    • 使用HttpRequest.TimedOut取消令牌。
    • (仅限于WebForms/RegisterAsyncTask)您可以通过设置Page.AsyncTimeout和让async方法接受CancellationToken来添加异步超时。

票数 2
EN

Stack Overflow用户

发布于 2013-07-11 07:23:43

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

粗糙规则:如果某物返回一个任务(方法名中包含“异步”),则必须等待它。

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

代码语言:javascript
复制
DumpEntities1 MyDumpEntities = new DumpEntities1();
var data = await MyDumpEntities.AgeGroups.ToListAsync();
var dataFromMyMethod = await MyasyncMethod()
Response.Write("f");
MyDumpEntities.Dispose();

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17587157

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档