Вызов синхронного асинхронного метода

У меня есть метод async :

 public async Task GenerateCodeAsync() { string code = await GenerateCodeService.GenerateCodeAsync(); return code; } 

Мне нужно вызвать этот метод синхронным методом.

Как я могу это сделать без дублирования метода GenerateCodeAsync чтобы это работало синхронно?

Обновить

Однако разумного решения не найдено.

Однако я вижу, что HttpClient уже реализует этот шаблон

 using (HttpClient client = new HttpClient()) { // async HttpResponseMessage responseAsync = await client.GetAsync(url); // sync HttpResponseMessage responseSync = client.GetAsync(url).Result; } 

Вы можете получить доступ к свойству Result задачи, что приведет к блокировке streamа до получения результата:

 string code = GenerateCodeAsync().Result; 

Примечание. В некоторых случаях это может привести к тупику: ваш вызов функции « Result блокирует основной stream, тем самым предотвращая выполнение оставшейся части асинхронного кода. У вас есть следующие опции, чтобы убедиться, что этого не происходит:

  • Добавьте .ConfigureAwait(false) в свой библиотечный метод или
  • явно выполните ваш метод async в streamе пула streamов и дождитесь его завершения:

     string code = Task.Run(GenerateCodeAsync).Result; 

Вы должны получить awaiter ( GetAwaiter() ) и закончить ожидание завершения асинхронной задачи ( GetResult() ).

 string code = GenerateCodeAsync().GetAwaiter().GetResult(); 

Вы должны это сделать, используя delegates, выражение lambda

 private void button2_Click(object sender, EventArgs e) { label1.Text = "waiting...."; Task sCode = Task.Run(async () => { string msg =await GenerateCodeAsync(); return msg; }); label1.Text += sCode.Result; } private Task GenerateCodeAsync() { return Task.Run(() => GenerateCode()); } private string GenerateCode() { Thread.Sleep(2000); return "I m back" ; } 

Мне нужно вызвать этот метод синхронно.

Это можно сделать с помощью GenerateCodeAsync().Result или GenerateCodeAsync().Wait() , как предлагает другой ответ. Это блокирует текущий stream до завершения GenerateCodeAsync .

Однако ваш вопрос помечен asp.net , и вы также оставили комментарий:

Я надеялся на более простое решение, считая, что asp.net обрабатывает это намного проще, чем писать так много строк кода

Я хочу сказать , что вы не должны блокировать asynchronous метод в ASP.NET. Это уменьшит масштабируемость вашего веб-приложения и может создать тупик (когда AspNetSynchronizationContext продолжения внутри GenerateCodeAsync отправляется в AspNetSynchronizationContext ). Использование Task.Run(...).Result для того, чтобы выгрузить что-то в stream пула, а затем заблокировать, еще больше повредит масштабируемость, поскольку он обрабатывает +1 больше streamа для обработки заданного HTTP-запроса.

ASP.NET имеет встроенную поддержку асинхронных методов либо через асинхронные controllerы (в ASP.NET MVC и Web API), либо напрямую через AsyncManager и PageAsyncTask в classическом ASP.NET. Вы должны использовать его. Для получения дополнительной информации проверьте этот ответ .

У Microsoft Identity есть методы расширения, которые синхронно вызывают методы асинхронного доступа. Например, существует метод GenerateUserIdentityAsync () и равный CreateIdentity ()

Если вы посмотрите UserManagerExtensions.CreateIdentity (), это выглядит так:

  public static ClaimsIdentity CreateIdentity(this UserManager manager, TUser user, string authenticationType) where TKey : IEquatable where TUser : class, IUser { if (manager == null) { throw new ArgumentNullException("manager"); } return AsyncHelper.RunSync(() => manager.CreateIdentityAsync(user, authenticationType)); } 

Теперь давайте посмотрим, что делает AsyncHelper.RunSync

  public static TResult RunSync(Func> func) { var cultureUi = CultureInfo.CurrentUICulture; var culture = CultureInfo.CurrentCulture; return _myTaskFactory.StartNew(() => { Thread.CurrentThread.CurrentCulture = culture; Thread.CurrentThread.CurrentUICulture = cultureUi; return func(); }).Unwrap().GetAwaiter().GetResult(); } 

Итак, это ваш обертку для асинхронного метода. И, пожалуйста, не читайте данные из Result – это потенциально блокирует ваш код в ASP.

Есть еще один способ – это подозрительно для меня, но вы тоже можете его рассмотреть

  Result r = null; YourAsyncMethod() .ContinueWith(t => { r = t.Result; }) .Wait(); 
  • Как ограничить количество одновременных операций асинхронного ввода-вывода?
  • Секвенирование и реорганизация задач
  • Отмена ожидающей задачи синхронно в streamе пользовательского интерфейса
  • Запуск задач в foreach Loop использует значение последнего элемента
  • Должны ли мы переключиться на использование асинхронного ввода-вывода по умолчанию?
  • Запуск двух асинхронных задач параллельно и сбор результатов в .NET 4.5
  • Лучший способ конвертировать метод async на основе обратного вызова в ожидаемую задачу
  • Interesting Posts

    Как отобразить другое значение для выпадающего списка значений / выбранного элемента в WPF ComboBox?

    Сохранение параметров строки запроса запроса GET в форме JSF

    Как определить несколько имен для поля XmlElement?

    Что такое фильтры с верхним и нижним проходом?

    Все начальные пункты меню исчезли

    Список «Поле» iCalendar (для схемы базы данных на основе стандарта iCalendar)

    Получить список различных значений в списке

    Невозможно десериализовать экземпляр java.util.ArrayList из токена START_OBJECT

    Должен ли я устанавливать 64-разрядные версии операционных систем?

    Самоподписанный сертификат SSL или CA?

    Что такое методы расширения?

    Windows не может найти «.exe» – только некоторые приложения

    сгруппированные операции, которые приводят к длине, не равной 1 или длине группы в dplyr

    NodeJS / express: код состояния кэша и 304

    Почему я получаю SEHException при вызове функции RoleEnvironment.GetConfigurationSettingValue («MYKEY»)?

    Давайте будем гением компьютера.