1

Я скачал EF6 (для того, чтобы использовать async)EntityFramework (6) и async (waitingForActivation)?

Так что я написал этот простой метод:

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 я вижу это :

enter image description here

п.с. это ToListAsync подпись enter image description here

Что мне не хватает?

+0

Вы не 'await'ing этот вызов, вероятно, вы должны пойти на' данных вар = ждут MyDumpEntities.AgeGroups.ToListAsync() '... –

+0

Он не ожидает вызова в вызов метода MyasyncMethod(), который возвращает задачу? – CodingIntrigue

+0

@ PatrykĆwiek noope http://i.stack.imgur.com/WqdZb.png –

ответ

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" в директиве страницы

+0

Я думал, что если 'MyasyncMethod' уже помечен как async, мне не нужно делать это также в' page_load' ........ bummer –

+0

@RoyiNamir Ну, если вы хотите использовать 'await' внутри метод, этот конкретный метод должен быть помечен как 'async'. Конечно, неплохо пойти «асинхронно», даже в вспомогательных методах ... –

+0

'async all the way down' - хорошо сказано. не знал, что я должен это сделать. –

1

ToListAsync возвращает Task. Отметьте Page_Load как асинхронный, тогда вы можете использовать его в ожидании.

Правило грубой проверки: если что-то возвращает задачу (содержит «Async» в имени метода), вы должны ее ждать.

Кроме того, при использовании async/wait вам не нужно использовать ContinueWith. Просто дождитесь своего метода и поместите вызов Write в следующую строку.

DumpEntities1 MyDumpEntities = new DumpEntities1(); 
var data = await MyDumpEntities.AgeGroups.ToListAsync(); 
var dataFromMyMethod = await MyasyncMethod() 
Response.Write("f"); 
MyDumpEntities.Dispose(); 

и добавить Async="True" в директиве страницы

+0

Спасибо за ваш ответ. –

2

Другие отмечают, что правильное решение заключается в использовании 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 есть единичная точка синхронизации, где среда выполнения ожидает завершения всех операций. See this article for how to use RegisterAsyncTask.
  5. Создайте собственные таймауты. Асинхронные запросы ASP.NET автоматически не используют обычные тайм-ауты, которые встроены в синхронные запросы ASP.NET. Существует два варианта:
    • Используйте токен HttpRequest.TimedOut.
    • (только для WebForms/RegisterAsyncTask) Вы можете добавить асинхронный таймаут, установив Page.AsyncTimeout и используя метод async, принять CancellationToken.
+1

Я думаю, что в статье отсутствует async. http://i.stack.imgur.com/P3mnN.png (точно моя ситуация здесь) –

Смежные вопросы