What are the circumstances of using .Wait () when calling async methods

In my asp.net mvc-5 web app, there is the following async long method: -

  public async Task<ScanResult> ScanAsync(string FQDN) { // sample of the operation i am doing var c = await context.SingleOrDefaultAsync(a=>a.id == 1); var list = await context.Employees.ToListAsync(); await context.SaveChangesAsync(); //etc.. } 

and I use the Hangfire tool, which supports running background jobs to promptly call this asynchronous use method, but inaccurate the hangefire tool does not support the direct async calling methods. therefore, to overcome this problem, I created a synchronization version of the above method, as shown below: -

 public void Scan() { ScanAsync("test").Wait(); } 

then from the HangFire scheduler, I call the synchronization method as follows: -

 RecurringJob.AddOrUpdate(() => ss.Scan(), Cron.Minutely); 

so I know that using .Wait() will basically take up the iis thread during the execution of the method, but as I said, I need to do it this way since I cannot directly call async TASK inside the hangefire scheduler.

so what happens when I use .Wait() to call the async? method, will the operations of the whole method be executed synchronously? for example, as shown above, I have three asynchronous operations inside ScanAsync() ; SingleOrDefualtAsync , ToListAsync and SaveChangesAsync , so they will execute synchronously, because I call the ScanAsync method using .wait ()?

+2
source share
2 answers

so what happens when I use .Wait () to call the async method ?, will the operations of the whole method be executed synchronously? for example, as shown above, I have three asynchronous operations inside ScanAsync (), SingleOrDefualtAsync, ToListAsync and SaveChangesAsync, so they will be executed in a synchronized way, because I call the ScanAsync method using .wait ()?

The methods that query the database will continue to be executed asynchronously, but the fact that you call Wait means that even if you free the thread, it will not return to ASP.NET ThreadPool as you stop it.

This is also an opportunity for deadlocks because ASP.NET has a custom synchronization context that ensures that the request context is available when continuing with an asynchronous call.

I would recommend using the synchronous API provided by the entity infrastructure instead, as you really cannot use the scalability that you can get from asynchronous calls.

Edit:

In the comments you asked:

How am I doing with hangefire now to eliminate the effect of asynchrony? if so, is it better to use synchronization methods? or using synchronization or asynchronous mode with hangeffire will be exactly the same

First, you need to understand the benefits of async. You do not do it because it is cool; you do it because it serves the purpose. What is this goal? Ability to scale under load. How does it do this? When you await asynchronous method, control returns back to the caller. For example, you have an incoming query, you are querying a database. You can sit there and wait for the request to complete, or you can reuse this thread to serve more incomplete requests. This is true power.

If you are not really planning on receiving a decent amount of requests (for example, you will starve the thread pool), you will not see any benefit from asynchronous use. Currently, as you have implemented it, you will not see any of these advantages, because you are blocking asynchronous calls. All that you see may be deadlocks.

+3
source

It really depends on how you implement HangFire . If it just starts the tasks that should be called in ThreadPool , the only effect will be that one of your threads will be blocked until the request is completed. However, if there is a custom SynchronizationContext , this can lead to a serious deadlock.

Think about it if you really want to wait until the planned work is completed. Maybe all you need is just fire and forget the pattern. So your method will look like this:

 public void Scan() { ScanAsync("test"); // smoothly ignore the task } 

If you need to wait, try using the async void method:

 public async void Scan() { await ScanAsync("test"); DoSomeOtherJob(); } 

There is a lot of debate about using async void , because you cannot wait for this method to complete and you will not be able to handle possible errors.

However, in an event-driven application, this may be the only way. For more information, you can refer to Async Void, ASP.Net and the number of outstanding transactions.

0
source

Source: https://habr.com/ru/post/1266089/


All Articles