Relax, as Microsoft itself says (http://msdn.microsoft.com/en-us/library/system.web.httpcontext.allowasyncduringsyncstages.aspx):
This behavior is meant as a safety net to let you know early on if you're writing async code that doesn't fit expected patterns and might have negative side effects.
Just remember a few simple rules:
Never await inside (async or not) void events (as they return immediately). Some WebForms Page events support simple awaits inside them - but
RegisterAsyncTask
is still the highly preferred approach.Don't await on async void methods (as they return immediately).
Don't wait synchronously in the GUI or Request thread (
.Wait()
,.Result()
,.WaitAll()
,WaitAny()
) on async methods that don't have.ConfigureAwait(false)
on root await inside them, or their rootTask
is not started with.Run()
, or don't have theTaskScheduler.Default
explicitly specified (as the GUI or Request will thus deadlock).Use
.ConfigureAwait(false)
orTask.Run
or explicitly specifyTaskScheduler.Default
for every background process, and in every library method, that does not need to continue on the synchronization context - think of it as the "calling thread", but know that it is not one (and not always on the same one), and may not even exist anymore (if the Request already ended). This alone avoids most common async/await errors, and also increases performance as well.
Microsoft just assumed you forgot to wait on your task...
UPDATE: As Stephen clearly (pun not intended) stated in his answer, there is an inherit but hidden danger with all forms of fire-and-forget when working with application pools, not solely specific to just async/await, but Tasks, ThreadPool, and all other such methods as well - they are not guaranteed to finish once the request ends (app pool may recycle at any time for a number of reasons).
You may care about that or not (if it's not business-critical as in the OP's particular case), but you should always be aware of it.