我已下载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
时,我看到了这一点:
P.S。这是ToListAsync
签名
我错过了什么?
答案 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_Load
。 Page_Load
然后为该任务附加一个继续,继续执行,处理上下文。因此,在ToListAsync
请求仍在运行时,可以处理上下文。
await
也为您解决了这个问题,因为它会“暂停”Page_Load
方法,直到MyasyncMethod
完成。
最后一点,在ASP.NET中使用async
时还应考虑以下几点:
Microsoft.Bcl.Async
。targetFramework
设置为4.5,或将UseTaskFriendlySynchronizationContext
设置为true。Page.Async
设置为true。RegisterAsyncTask
代替await
。我通常更喜欢await
,因为不同的方法有更多的关注点分离,但ASP.NET团队更喜欢RegisterAsyncTask
因为PreRender
之后只有一个“同步”点,运行时等待所有要完成的操作。 See this article for how to use RegisterAsyncTask
. HttpRequest.TimedOut
取消令牌。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"
添加到页面指令