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 :
p.s. this is the ToListAsync
signature
What am I missing ?
ToListAsync
returns aTask
. MarkPage_Load
as async, then you can use await in it.Rough rule: If something returns a Task (contains "Async" in method name), you have to await it.
Also, when using async/await you don't have to use
ContinueWith
. Just await your own method and place theWrite
call in the next line.and add
Async="True"
to the page directiveBasing it of off the comments and the line that you have problem with:
What will
data
type be?Task<List<AgeGroup>>
. That's right, notList<AgeGroup>
. So, you either have to mark thePage_Load
as async (if possible):Or wait for the execution somehow (continuation, blocking wait).
Another thing (someone else might want to correct that if I'm wrong), but since you're using continuation for the second call, I would be very careful of disposing the context outside of continuation. It might turn out that you dispose the context preemptively. In this particular case, you're not using the context in the continuation, but it looks suspicious...
So I'd either
Or just use
async
there tooand add
Async="True"
to the page directiveOthers have pointed out that the correct solution is to use
await
, but I don't see a good explanation of why.There are two reasons why the original code is wrong. First, you're using
ContinueWith
without capturing the context in an ASP.NET application, so the continuation (theResponse.Write
call) does not have a request context and therefore has no response to write to.await
takes care of this for you by capturing the context before theawait
and using that to resume the rest of the method; in this case, it will capture anAspNetSynchronizationContext
representing the current request/response.The other reason is that asynchronous code will run concurrently. So,
MyasyncMethod
will begin executing, reach itsawait
, and return an uncompleted task toPage_Load
.Page_Load
then attaches a continuation to that task and continues executing, disposing the context. So the context may be disposed while theToListAsync
request is still running.await
also fixes this for you because it will "pause" thePage_Load
method untilMyasyncMethod
is complete.As a final note, you should also consider these points when using
async
in ASP.NET:Microsoft.Bcl.Async
.targetFramework
to 4.5, or setUseTaskFriendlySynchronizationContext
to true.Page.Async
to true.RegisterAsyncTask
instead ofawait
. I usually preferawait
because different methods have more separation of concerns, but the ASP.NET team prefersRegisterAsyncTask
because there is a single "synchronize" point afterPreRender
where the runtime waits for all the operations to complete. See this article for how to useRegisterAsyncTask
.HttpRequest.TimedOut
cancellation token.RegisterAsyncTask
only) You can add an asynchronous timeout by settingPage.AsyncTimeout
and having yourasync
method take aCancellationToken
.