1

I've downloaded EF6 ( in order to use async)

So I wrote this simple method :

  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();

But I don't see anything on the screen and when I inspect data I see this :

enter image description here

p.s. this is the ToListAsync signature enter image description here

What am I missing ?

4

3 回答 3

3

基于评论和您有问题的行:

var data = MyDumpEntities.AgeGroups.ToListAsync();

类型会是什么dataTask<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"到页面指令

于 2013-07-11T07:25:38.410 回答
2

其他人指出正确的解决方案是使用await,但我没有很好地解释为什么

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

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

另一个原因是异步代码将同时运行。因此,MyasyncMethod将开始执行,到达其await,并将未完成的任务返回给Page_LoadPage_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之后有一个“同步”点。请参阅这篇文章了解如何使用.PreRenderRegisterAsyncTask
  5. 构建您自己的请求超时。异步 ASP.NET 请求不会自动使用内置于同步 ASP.NET 请求的正常超时。有两种选择:
    • 使用HttpRequest.TimedOut取消令牌。
    • (仅限 WebForms/ RegisterAsyncTask)您可以通过设置Page.AsyncTimeout并让您的async方法采用CancellationToken.
于 2013-07-11T10:39:22.973 回答
1

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

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

此外,当使用 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"到页面指令

于 2013-07-11T07:23:43.203 回答