2016-08-24 2 views
0

У меня есть следующий код, в котором я использую async-ключевое слово в моем предложении GroupBy, однако мне говорят, что этот вызов не ожидается и будет выполняться синхронно , мой вопрос состоит в том, будут ли мои два звонка GetAllLanguages и GetAllStores, а мой последующий вызов Task.WaitAll(languagesTask, storesTask); использует функции async или все мои коды запускаются синхронно, так как я не ожидаю оператора GroupBy. также можно дождаться звонка .GroupBy(async resourceApplicationType ...Я получаю преимущества async и жду в следующем коде

public async Task UpdateAllResources() 
     { 
      var applicationTypes = databaseSettings.Select(dbcs => dbcs.ResourceApplicationType); 
      var commandsPerApplication = applicationTypes 
       .GroupBy(async resourceApplicationType => 
       { 
        var languagesTask = GetAllLanguages(resourceApplicationType); 
        var storesTask = GetAllStores(resourceApplicationType); 
        var resourceCategory = ResourceApplicationToCategoriesMapper.Map(resourceApplicationType); 
        Task.WaitAll(languagesTask, storesTask); 
        var commands = from category in resourceCategory 
          from language in languagesTask.Result 
          from store in storesTask.Result 
          select new UpdateResourcesCommand 
          { 
           ApplicationType = resourceApplicationType, 
           StoreCode = store.Code, 
           LocaleCode = language.Locale, 
           ResourceCategory = category 
          }; 
        return new 
        { 
         applicationType = resourceApplicationType, commands 
        }; 
       }); 

      commandsPerApplication.ForEach(commandsGroup => 
      { 
       commandsGroup.Key.Result.commands.ForEach(async command => 
       { 
        await commandExecutor.Execute<UpdateResourcesCommand, Task>(command); 
       }); 
      }); 
     } 

     private Task<IEnumerable<Language>> GetAllLanguages(ResourceApplication applicationType) 
     { 
      return allLanguagesQueryRetriever.GetByComponentName(InstanceName.GetUniqueName<IAllLanguagesQuery>(applicationType.ToString())) 
       .Execute(new AllLanguagesCriteria()); 
     } 

     private Task<IEnumerable<Store>> GetAllStores(ResourceApplication applicationType) 
     { 
      return allStoresQueryRetriever 
       .GetByComponentName(InstanceName.GetUniqueName<IAllStoresQuery>(applicationType.ToString())) 
       .Execute(new AllStoresCriteria()); 
     } 
+0

Вы не ожидал 'Task.WaitAll (languagesTask, storesTask);' в 'UpdateAllResources'. Это может означать, что задача еще не закончена, прежде чем вы попытаетесь получить доступ к результату. – JConstantine

+0

@JLevett это утверждение не является ожидаемым. «Тип void не является ожидаемым», он, по сути, ожидает. – Xerxes

+0

Приношу свои извинения. Вы также можете использовать 'await Task.WhenAll()' – JConstantine

ответ

0

Основное правило: «Без ожидания, асинхронный режим будет работать синхронно».

Вы можете легко получить GroupBy() для правильной работы async путем обмена Task.WaitAll() на await Task.WhenAll().

+0

Мне по-прежнему требуется, чтобы объект объекта result 'commandsGroup.Key.Result.commands.ForEach (async command =>' после использования WhenAll, это нормально? Я бы подумал, что если бы я все ждал, тогда я мог бы просто обойти вызов. Результат ?! – Xerxes

+0

К сожалению, это не работает, если вы ожидаете отдельных задач и назначаете их результаты непосредственно переменной, например, 'var languages ​​= await GetAllLanguages ​​()' – JConstantine

0

Код здесь имеет большую тревогу таится вокруг из-за неправильного async-await использования, хотя в центре внимания здесь почему async код работает Synchronously, что, безусловно, из-за отсутствия использования await ключевого слова, но, как объяснил это может быть только на Task не возвращается void, для которого вам, безусловно, необходимо Task.WhenAll().

Я мало удивляюсь, что методы GetAllLanguages и GetAllStores, которые связаны с IO не async.

В случае, если вы планируете запускать код Synchronously, то не было бы тупиковый из-за Task.WaitAll(), особенно для кода, который нуждается в UI Synchronization context, что ничего, кроме Console application.

Короче метода Асинхронного возвращающий Task связан тупиковой ситуация с Task.WaitAll(), если ждал в Synchronous manner, а UI thread/Synchronization context блоков самого