EntityFramework (6) и async (waitingForActivation)?

.net-4.5 async-await c# entity-framework entity-framework-6

Вопрос

Я загрузил 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 я вижу это:

введите описание изображения здесь

ps это подпись ToListAsync введите описание изображения здесь

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

Принятый ответ

Основываясь на комментариях и линии, с которой у вас возникли проблемы:

var data = MyDumpEntities.AgeGroups.ToListAsync();

Каким будет тип data ? Task<List<AgeGroup>> . Правильно, но не List<AgeGroup> . Таким образом, вы либо должны пометить Page_Load как async (если возможно):

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


Популярные ответы

Другие отметили, что правильное решение - это использовать await , но я не вижу правильного объяснения причин .

Есть две причины, по которым исходный код неверен. Во-первых, вы используете ContinueWith без захвата контекста в приложении ASP.NET, поэтому продолжение (вызов Response.Write ) не имеет контекста запроса и, следовательно, не имеет ответа на запись.

await позаботится об этом для вас, захватив контекст перед await и используя его для возобновления остальной части метода; в этом случае он захватит AspNetSynchronizationContext представляющий текущий запрос / ответ.

Другая причина заключается в том, что асинхронный код будет работать одновременно. Итак, MyasyncMethod начнет выполнение, дойдет до его await и вернет незавершенную задачу в Page_Load . Page_Load затем прикрепляет продолжение к этой задаче и продолжает выполнение , избавляя контекст. Таким образом, контекст может быть ToListAsync запрос ToListAsync все еще запущен.

await также исправляет это для вас, потому что оно «приостанавливает» метод Page_Load до MyasyncMethod пор, пока MyasyncMethod будет закончен 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 точка PreRender где среда выполнения ожидает завершения всех операций. См. Эту статью о том, как использовать RegisterAsyncTask .
  5. Создайте собственные таймауты запросов. Асинхронные запросы ASP.NET автоматически не используют обычные тайм-ауты, которые встроены в синхронные запросы ASP.NET. Существует два варианта:
    • Используйте токен HttpRequest.TimedOut .
    • (Только для WebForms / RegisterAsyncTask ). Вы можете добавить асинхронный таймаут, установив параметр Page.AsyncTimeout и используя метод async для CancellationToken .


Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему