I am new with async methods in MVC C#, so I tried some examples from This tutorial
So I coded a class with a method for saving 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 controller has a method that calls my registerCardTokenAsync
[HttpPost]
public ActionResult IngresarTargeta(CreditCardViewModel creditCardViewModel)
{
//do something here....
//do another thing....
var query = MyClass.RegisterCardTokenAsync(creditCardToken);
query.Wait();
}
In theory we use query.Wait() to "wait" until the operation is finished. My problem is that in my database the CreditCardToken is saved, however, my application just freezes.
Why is this happening and how can I solve it?
As far as I know await is required when executing FirstOrDefaultAsync().
Don't synchronously wait on async calls, unless you are completely aware of the context, let async propagate .
public async Task<ActionResult> IngresarTargeta(CreditCardViewModel creditCardViewModel)
{
var result = await MyClass.RegisterCardTokenAsync(creditCardToken)
Here is why
The top-level method calls RegisterCardTokenAsync (within the ASP.NET context).
RegisterCardTokenAsync starts the save changes by calling _dbContext.SaveChangesAsync() (still within the context).
SaveChangesAsync returns an uncompleted Task, indicating the save is not complete.
RegisterCardTokenAsync awaits the Task returned by SaveChangesAsync. The context is captured and will be used to continue running the SaveChangesAsync method later. SaveChangesAsync returns an uncompleted Task, indicating that the SaveChangesAsync method is not complete.
The top-level method synchronously blocks on the Task returned by SaveChangesAsync. This blocks the context thread.
...
Eventually, the SaveChangesAsync will complete. This completes the Task that was returned by SaveChangesAsync.
The continuation for RegisterCardTokenAsync is now ready to run, and it waits for the context to be available (so it can execute in the context).
This results in a deadlock. The top-level method is blocking the context thread waiting for RegisterCardTokenAsync to complete, and RegisterCardTokenAsync is waiting for the context to be freed so it can complete.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With