query.wait не заканчивается - PullRequest
       1

query.wait не заканчивается

0 голосов
/ 22 октября 2018

Я новичок в асинхронных методах в MVC C #, поэтому я попробовал несколько примеров из Этот урок

Итак, я закодировал класс с методом для сохранения creditcardtoken

public  async Task<CreditCardToken> RegisterCardTokenAsync(CreditCardToken creditCardToken)
{
    if (creditCardToken == null) return null;
    creditCardToken.number = creditCardToken.maskedNumber;
    _dbContext.CreditCardToken.Add(creditCardToken);
    var saveChanges = await (_dbContext.SaveChangesAsync());
    if (saveChanges > 0) return creditCardToken;
    else return null;
}

У моего контроллера есть метод, который вызывает my registerCardTokenAsync

[HttpPost]
public ActionResult IngresarTargeta(CreditCardViewModel creditCardViewModel)
{
    //do something here....
    //do another thing....

    var query = MyClass.RegisterCardTokenAsync(creditCardToken);
    query.Wait();
 }

Теоретически мы используем query.Wait(), чтобы "дождаться" завершения операции.Моя проблема в том, что в моей базе данных CreditCardToken сохраняется, однако мое приложение просто зависает.

Почему это происходит и как я могу решить эту проблему?

Насколько я знаю, ждуттребуется при выполнении FirstOrDefaultAsync().

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Не следует синхронно ожидать вызовов async, если вы не полностью осведомлены о контексте, и пусть async распространяется.

public async Task<ActionResult> IngresarTargeta(CreditCardViewModel creditCardViewModel)
{
   var result = await MyClass.RegisterCardTokenAsync(creditCardToken)

Вот почему

  • Метод верхнего уровня вызывает RegisterCardTokenAsync (в контексте ASP.NET).

  • RegisterCardTokenAsync запускает изменения сохранения, вызывая _dbContext.SaveChangesAsync() (все еще в контексте).

  • SaveChangesAsync возвращает незавершенный Task, указывая, что сохранение не завершено.

  • RegisterCardTokenAsync ожидает Task, возвращаемое SaveChangesAsync.Контекст захвачен и будет использован для продолжения запуска метода SaveChangesAsync позже.SaveChangesAsync возвращает незавершенный Task, указывая, что метод SaveChangesAsync не завершен.

  • Метод верхнего уровня синхронно блокирует Task, возвращаемый SaveChangesAsync,Это блокирует поток контекста.

...

  • В конце концов, SaveChangesAsync завершится.Это завершает Task, который был возвращен SaveChangesAsync.

  • Продолжение для RegisterCardTokenAsync теперь готово к запуску, и оно ожидает, что контекст будет доступен (так чтоможет выполняться в контексте).

Это приводит к взаимоблокировке .Метод верхнего уровня блокирует поток контекста, ожидая завершения RegisterCardTokenAsync, а RegisterCardTokenAsync ожидает освобождения контекста, чтобы он мог завершиться.

0 голосов
/ 22 октября 2018

Теоретически вы должны сделать все функции асинхронными

[HttpPost]
public async Task<ActionResult> IngresarTargeta(CreditCardViewModel creditCardViewModel)
{
    //do something here....
    //do another thing....

     var token = await MyClass.RegisterCardTokenAsync(creditCardToken);
     Ok(token);
 }

Очень хороший ресурс: Не блокировать асинхронный код

Обратите внимание, что в ASP.NET Coreваш код будет работать, потому что он не использует SynchronizationContext.Но все равно было бы неправильно блокировать асинхронные методы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...