Why not use a sync method instead of await Async task? - c#

Async method:
public void Main(){
await Asynctask1;
DoSomething();
}
public async Task AsyncTask1(){
//Async logic here
}
Sync method:
public void Main(){
SyncMethod1();
DoSomething();
}
I think I'm missing something here. Assuming that SyncMethod1() and Asynctask1() both do the same thing, aren't these 2 constructs in the end the same result, namely that DoSomething() doesn't start until the method before finishes?

namely that DoSomething() doesn't start until the method before finishes?
There's a difference between asynchrony and sequential. When you always await your asynchronous methods immediately, you end up with asynchronous sequential code, which at first glance does appear to behave similarly to synchronous sequential code. (On a side note, this similarity is the entire point of the async/await keywords). However, there's one important difference.
Let's say the operation is some I/O thing, like getting an HTTP resource. SyncMethod1 will do the HTTP get synchronously; that is, it sends out the HTTP request and then blocks the thread until it gets the HTTP response. AsyncTask1 will do the HTTP get asynchronously; that is, it sends out the HTTP request and then returns an incomplete Task. Later, when the HTTP request comes in, the AsyncTask1 method will resume and complete the returned Task, and the code after the await is run (i.e., DoSomething).
The asynchronous way is more complicated but has one key advantage: it does not block a thread. So, UI threads are freed to enable a responsive UI and ASP.NET threads are freed to handle other requests.
I have an async intro on my blog that may help as you learn.

In the case you have outlined there is no practical difference as you immeadiately wait for the asynchronous method to complete before moving on to the next.
However, if you restructured your code something like this you might realize the power of asynchronous programming:
public async void Main() {
Task performTask = AsyncTask1();
//This method can continue without having to wait for AsyncTask1 to complete
DoSomething();
//Here we await the AsyncTask1 because perhaps other code further
//down is depending on it
await performTask;
}

Related

Async/Await and Web API blocks execution

I have the following in my REST API server(using OWIN):
[ResponseType(typeof(Session))]
[Route("api/v1/async")]
public Session async_status()
{
AsyncStatus();
return new Session() {...};
}
private async Task<int> AsyncStatus()
{
await SyncMethod();
return 42;
}
private Task<int> SyncMethod()
{
CopyFileThatTakesALongTime(....);
// OR
Thread.Sleep(60000);
return Task.FromResult(42);
}
Why dies it block and the client does not get the desired asynchronous-ness. I I would expect that when calling:
await SyncMethod();
The caller would be freed and unblocked while the rest of the sleep would be executed. What am i missing?
P.S: I can easily fix it by replacing this:
AsyncStatus();
With:
Task.Run(() => AsyncStatus() );
The reason i am not doing that is because of this reading:
https://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-using.html
In other words if it's bad to use Task.Run() in a web server as in the above article but you can't use async/await, what is the solution?
An async method only becomes asynchronous when asynchronous work starts.
That is, all of your code will run synchronously until something truly asynchronous starts. Once some truly asynchronous work starts, a Task is returned up the call stack, which then can be awaited (or not) by the calling methods.
The implication of this is that an async method could still hold up the request if you're doing a lot of synchronous work before the asynchronous work. Your example shows that perfectly. Let's break down exactly what a thread is doing:
Start running async_status()
Jump to AsyncStatus()
At await SyncMethod() the thread jumps to SyncMethod().
The thread halts at Thread.Sleep(60000) for 60 seconds.
SyncMethod() returns a complete Task.
Because there is nothing to await, AsyncStatus() continues synchronously and returns a value.
async_status() returns and thus the request.
Thread.Sleep(60000) can be replaced with any processor-intensive task (or any long-running non-async task) and the result would be the same if it happens before the first await in that method.
This is also described in Microsoft's documentation under the heading What happens in an async method. Notice point 3:
Something happens in GetStringAsync that suspends its progress. Perhaps it must wait for a website to download or some other blocking activity. To avoid blocking resources, GetStringAsync yields control to its caller, AccessTheWebAsync.
Control only returns to the calling method when a Task is returned, which only happens when an asynchronous task is actually started. In your example, there isn't any asynchronous task happening. If you added one (even just await Task.Delay(1)) you would see different results. For example, this will return right away:
[ResponseType(typeof(Session))]
[Route("api/v1/async")]
public Session async_status()
{
AsyncStatus();
return new Session() {...};
}
private async Task<int> AsyncStatus()
{
await SyncMethod();
return 42;
}
private async Task<int> SyncMethod()
{
await Task.Delay(1);
Thread.Sleep(60000);
return 42;
}
At await Task.Delay(1) (or any truly asynchronous work):
SyncMethod() returns an incomplete Task to AsyncStatus()
AsyncStatus() returns an incomplete Task to async_status().
That Task is not awaited, so execution of async_status() continues
To answer your question:
You asked:
if it's bad to use Task.Run() in a web server as in the above article but you can't use async/await, what is the solution?
You mentioned the Task.Run Etiquette article. Read his conclusion at the end:
Do not use it just to “provide something awaitable for my async method to use”.
Your purpose here is not to just "provide something awaitable", but to start a background job and not make the client wait until it's done. That's different.
So yes, you could actually use Task.Run(). However, as noted in Stephen Cleary's Fire and Forget on ASP.NET article, the problem with doing it this way is that ASP.NET does not keep track of that background task. So if it's long-running, then recycling the app pool could immediately kill that work. His article describes better methods of performing background work that you don't want to hold up the return of the request.

Is a method always async if it has the key word "async" and "await"? [duplicate]

I've been trying to understand async/await and Task in C# but have been failing spectacularly despite watching youtube videos, reading documentation and following a pluralsight course.
I was hoping someone might be able to help answer these slightly abstract questions to help my brain out.
1.Why do they say that async/await enables an 'asynchonrous' method when the async keyword on it's own does nothing and the await keyword adds a suspension point? Isn't adding a suspension point forcing the method to act synchronously, i.e. finish the task marked by the await before moving on.
2.Apparently you are not supposed to use async void except for event handlers, so how do you call an async method normally? It seems that in order to call an async method by using the await keyword, the method/class that is calling it itself needs to be marked as async. All the examples I've seen have 'initiated' an async void method with an event handler. How would you 'escape' this wrapping of async/await to run the method?
3.
public async Task SaveScreenshot(string filename, IWebDriver driver)
{
var screenshot = driver.TakeScreenshot();
await Task.Run(() =>
{
Thread.Sleep(2000);
screenshot.SaveAsFile(filename, ScreenshotImageFormat.Bmp);
Console.WriteLine("Screenshot saved");
});
Console.WriteLine("End of method");
}
Relating back to 1. this looks like a synchronous method. Execution pauses when it gets to Task.Run, therefore Console.WriteLine("End of method"); will not be executed until the task is finished. Maybe the whole method itself will be executed asynchronously at the point it is triggered in the code? But relating back to 2, you need to call this with an await otherwise you get the message 'Because this call is not awaited..' therefore adding an await will cause that execution point to be synchronous and so on and so.
Any help understanding this would be much appreciated.
Isn't adding a suspension point forcing the method to act synchronously, i.e. finish the task marked by the await before moving on.
No, the word you're thinking of is "sequential", not "synchronous". await results in asynchronous sequential code. "Sequential" meaning "one at a time"; "synchronous" meaning "blocking until completed".
how do you call an async method normally?
Using await.
How would you 'escape' this wrapping of async/await to run the method?
Ideally, you don't. You go async all the way. Modern frameworks (including ASP.NET MVC, Azure Functions / WebJobs, NUnit / xUnit / MSTest, etc) all allow you to have entry points that return Task. Less-modern frameworks (including WinForms, WPF, Xamarin Forms, ASP.NET WebForms, etc) all allow async void entry points.
So, ideally you do not call asynchronous code from synchronous code. This makes sense if you think about what asynchronous code is: the entire point of it is to not block the calling thread, so if you block the calling thread on asynchronous code, then you lose all the benefits of asynchronous code in the first place.
That said, there are rare situations where you do need to treat the code synchronously. E.g., if you are in the middle of a transition to async, or if you are constrained by a library/framework that is forcing your code to be synchronous and won't work with async void. In that case, you can employ one of the hacks in my article on brownfield async.
Your understanding is pretty good :). The main point you seem to be missing is that "asynchronous" methods in .NET mean methods that can stop execution without blocking the calling thread.
As you pointed out in (1), the async keyword basically enables the use of await and requires the return type to be void or Task/Task<T>. await just instructs the current method to suspend execution until the task is complete.
What you are missing here is that it suspends just the current method. It does not block the thread the method was executing on. This is important in cases like the UI thread of a WPF application. Suspend method execution and everything keeps running, block the thread and the application stops responding.
You usually want your async calls to go all the way to the top (like an event handler), this allows the most flexibility and prevents deadlock situations. However; you can wait for a Task returning method to complete with Wait:
someAsyncMethod.Wait()
Or get the return value:
var result = someAsyncMethod.Result;
Note that both of these are synchronous and block the calling thread. Doing this can cause deadlock if the async task is waiting for some other work on the calling thread to complete.
The above should answer your question in (3); the method itself appears to execute synchronously (this is the magic of await/async) but the task doesn't block the calling thread.
It is asynchronous because you don't have to wait the method to return. In your code, you may call the async method and save the task in a variable. Continue doing something else. Later, when the method result is needed, you await the response (task).
// Synchronous method.
static void Main(string[] args)
{
// Call async methods, but don't await them until needed.
Task<string> task1 = DoAsync();
Task<string> task2 = DoAsync();
Task<string> task3 = DoAsync();
// Do other stuff.
// Now, it is time to await the async methods to finish.
Task.WaitAll(task1, task2, task3);
// Do something with the results.
Console.WriteLine(task1.Result);
Console.ReadKey();
}
private static async Task<string> DoAsync()
{
Console.WriteLine("Started");
await Task.Delay(3000);
Console.WriteLine("Finished");
return "Success";
}
// Output:
// Started
// Started
// Started
// Finished
// Finished
// Finished
// Success

AsyncAwait Concept

I'm trying to understand the concept of async and await and can't quite grasp the concept of it. Up to what I've learned is in Async-await if we call a method-A and then call method-B using await from method-A then the reminder of method-A will run only after method-B's work is completed. Am I missing something? Please correct me.
If that is the case then every time we call a method even with using synchronous programming, the reminder of the method-A waits until we have finished calling method-B?
public void methodA(){
methodB();
Console.Writeline("MethodB has been called");
}
public void methodB(){//do stuff}
Now with async await:
public async Task methodA(){
await methodB();
Console.Writeline("MethodB has been called");
}
public async Task methodB(){//do stuff}
Please mind me showing the difference? I'm having really hard time trying to grasp the concept. Generally, I see posts on ThreadPool and Threads, but without having a clear concept, I don't quite get it.
async and await are about getting threads to do useful work rather than sitting idly waiting for other work to complete.
If we write code that creates a new thread to do some work, and then immediately block our current thread to wait for that to finish, that's a waste. Why would we not just run the code on our current thread and have it complete useful work, and save ourselves the overhead of creating a new thread?1
So, what does await do? It allows our current method to return to its caller sooner than when all of its work is complete. That is, we're indicating that we've got no current use for the thread that we're running on, but hopefully our caller, or our callers caller, etc, does have something else it can be usefully running on our thread.
What if our method has something else it can usefully do on the current thread? Easy - decouple the creation of an awaitable from the await itself, and do that other useful work between:
public async Task methodA(){
var mba = methodB();
Console.Writeline("MethodB has been called");
//Other useful work that doesn't depend on methodB
var result = await mba
//And now continue with the result from methodB
}
How methodB itself achieves its asynchrony is entirely an implementation detail of methodB - all we know is that it's arranged to complete its returned Task at some future point in time (this is why other languages use terms such as "futures" or "promises" where we use "task")
1For those wondering why this paragraph exists, it's to exactly rebut the all too common claim that await "creates a new thread" or similar.
Up to what I've learned is in Async-await if we call a method-A and then call method-B using await from method-A then the reminder of method-A will run only after method-B's work is completed.
You are kind of right.
Let's take a look at a practical situation where async await would be used.
Let's say you have a Windows Forms program. On the form, there is a button. When the user presses this button, the program will fetch some stuff from the internet. After the response is received, it displays the response in a label.
Obviously, requesting stuff on the internet takes a rather long time, compared to other operations like adding stuff together, drawing a text box etc.
If you don't use async-await, the form will not respond to user interactions while the program is waiting for the response from the server. That's bad UX.
Now let's use async-await. I will use the code that you have provided:
public async Task methodA(){
await methodB();
Console.Writeline("MethodB has been called");
}
public async Task methodB(){//do stuff}
methodA is called when the button is pressed. methodB fetches the data. When the await line is reached, methodA returns immediately just after methodB is called. This way, the program execution does not need to stay in methodA so the form can respond to user interactions. A state machine is created to remember where the execution was in methodA. After methodB returns, execution goes back to methodA and execute the rest of it.

Synchronous I/O within an async/await-based Windows Service

Let's say I have a Windows Service which is doing some bit of work, then sleeping for a short amount of time, over and over forever (until the service is shut down). So in the service's OnStart, I could start up a thread whose entry point is something like:
private void WorkerThreadFunc()
{
while (!shuttingDown)
{
DoSomething();
Thread.Sleep(10);
}
}
And in the service's OnStop, I somehow set that shuttingDown flag and then join the thread. Actually there might be several such threads, and other threads too, all started in OnStart and shut down/joined in OnStop.
If I want to instead do this sort of thing in an async/await based Windows Service, it seems like I could have OnStart create cancelable tasks but not await (or wait) on them, and have OnStop cancel those tasks and then Task.WhenAll().Wait() on them. If I understand correctly, the equivalent of the "WorkerThreadFunc" shown above might be something like:
private async Task WorkAsync(CancellationToken cancel)
{
while (true)
{
cancel.ThrowIfCancellationRequested();
DoSomething();
await Task.Delay(10, cancel).ConfigureAwait(false);
}
}
Question #1: Uh... right? I am new to async/await and still trying to get my head around it.
Assuming that's right, now let's say that DoSomething() call is (or includes) a synchronous write I/O to some piece of hardware. If I'm understanding correctly:
Question #2: That is bad? I shouldn't be doing synchronous I/O within a Task in an async/await-based program? Because it ties up a thread from the thread pool while the I/O is happening, and threads from the thread pool are a highly limited resource? Please note that I might have dozens of such Workers going simultaneously to different pieces of hardware.
I am not sure I'm understanding that correctly - I am getting the idea that it's bad from articles like Stephen Cleary's "Task.Run Etiquette Examples: Don't Use Task.Run for the Wrong Thing", but that's specifically about it being bad to do blocking work within Task.Run. I'm not sure if it's also bad if I'm just doing it directly, as in the "private async Task Work()" example above?
Assuming that's bad too, then if I understand correctly I should instead utilize the nonblocking version of DoSomething (creating a nonblocking version of it if it doesn't already exist), and then:
private async Task WorkAsync(CancellationToken cancel)
{
while (true)
{
cancel.ThrowIfCancellationRequested();
await DoSomethingAsync(cancel).ConfigureAwait(false);
await Task.Delay(10, cancel).ConfigureAwait(false);
}
}
Question #3: But... what if DoSomething is from a third party library, which I must use and cannot alter, and that library doesn't expose a nonblocking version of DoSomething? It's just a black box set in stone that at some point does a blocking write to a piece of hardware.
Maybe I wrap it and use TaskCompletionSource? Something like:
private async Task WorkAsync(CancellationToken cancel)
{
while (true)
{
cancel.ThrowIfCancellationRequested();
await WrappedDoSomething().ConfigureAwait(false);
await Task.Delay(10, cancel).ConfigureAwait(false);
}
}
private Task WrappedDoSomething()
{
var tcs = new TaskCompletionSource<object>();
DoSomething();
tcs.SetResult(null);
return tcs.Task;
}
But that seems like it's just pushing the issue down a bit further rather than resolving it. WorkAsync() will still block when it calls WrappedDoSomething(), and only get to the "await" for that after WrappedDoSomething() has already completed the blocking work. Right?
Given that (if I understand correctly) in the general case async/await should be allowed to "spread" all the way up and down in a program, would this mean that if I need to use such a library, I essentially should not make the program async/await-based? I should go back to the Thread/WorkerThreadFunc/Thread.Sleep world?
What if an async/await-based program already exists, doing other things, but now additional functionality that uses such a library needs to be added to it? Does that mean that the async/await-based program should be rewritten as a Thread/etc.-based program?
Actually there might be several such threads, and other threads too, all started in OnStart and shut down/joined in OnStop.
On a side note, it's usually simpler to have a single "master" thread that will start/join all the others. Then OnStart/OnStop just deals with the master thread.
If I want to instead do this sort of thing in an async/await based Windows Service, it seems like I could have OnStart create cancelable tasks but not await (or wait) on them, and have OnStop cancel those tasks and then Task.WhenAll().Wait() on them.
That's a perfectly acceptable approach.
If I understand correctly, the equivalent of the "WorkerThreadFunc" shown above might be something like:
Probably want to pass the CancellationToken down; cancellation can be used by synchronous code, too:
private async Task WorkAsync(CancellationToken cancel)
{
while (true)
{
DoSomething(cancel);
await Task.Delay(10, cancel).ConfigureAwait(false);
}
}
Question #1: Uh... right? I am new to async/await and still trying to get my head around it.
It's not wrong, but it only saves you one thread on a Win32 service, which doesn't do much for you.
Question #2: That is bad? I shouldn't be doing synchronous I/O within a Task in an async/await-based program? Because it ties up a thread from the thread pool while the I/O is happening, and threads from the thread pool are a highly limited resource? Please note that I might have dozens of such Workers going simultaneously to different pieces of hardware.
Dozens of threads are not a lot. Generally, asynchronous I/O is better because it doesn't use any threads at all, but in this case you're on the desktop, so threads are not a highly limited resource. async is most beneficial on UI apps (where the UI thread is special and needs to be freed), and ASP.NET apps that need to scale (where the thread pool limits scalability).
Bottom line: calling a blocking method from an asynchronous method is not bad but it's not the best, either. If there is an asynchronous method, call that instead. But if there isn't, then just keep the blocking call and document it in the XML comments for that method (because an asynchronous method blocking is rather surprising behavior).
I am getting the idea that it's bad from articles like Stephen Cleary's "Task.Run Etiquette Examples: Don't Use Task.Run for the Wrong Thing", but that's specifically about it being bad to do blocking work within Task.Run.
Yes, that is specifically about using Task.Run to wrap synchronous methods and pretend they're asynchronous. It's a common mistake; all it does is trade one thread pool thread for another.
Assuming that's bad too, then if I understand correctly I should instead utilize the nonblocking version of DoSomething (creating a nonblocking version of it if it doesn't already exist)
Asynchronous is better (in terms of resource utilization - that is, fewer threads used), so if you want/need to reduce the number of threads, you should use async.
Question #3: But... what if DoSomething is from a third party library, which I must use and cannot alter, and that library doesn't expose a nonblocking version of DoSomething? It's just a black box set in stone that at some point does a blocking write to a piece of hardware.
Then just call it directly.
Maybe I wrap it and use TaskCompletionSource?
No, that doesn't do anything useful. That just calls it synchronously and then returns an already-completed task.
But that seems like it's just pushing the issue down a bit further rather than resolving it. WorkAsync() will still block when it calls WrappedDoSomething(), and only get to the "await" for that after WrappedDoSomething() has already completed the blocking work. Right?
Yup.
Given that (if I understand correctly) in the general case async/await should be allowed to "spread" all the way up and down in a program, would this mean that if I need to use such a library, I essentially should not make the program async/await-based? I should go back to the Thread/WorkerThreadFunc/Thread.Sleep world?
Assuming you already have a blocking Win32 service, it's probably fine to just keep it as it is. If you are writing a new one, personally I would make it async to reduce threads and allow asynchronous APIs, but you don't have to do it either way. I prefer Tasks over Threads in general, since it's much easier to get results from Tasks (including exceptions).
The "async all the way" rule only goes one way. That is, once you call an async method, then its caller should be async, and its caller should be async, etc. It does not mean that every method called by an async method must be async.
So, one good reason to have an async Win32 service would be if there's an async-only API you need to consume. That would cause your DoSomething method to become async DoSomethingAsync.
What if an async/await-based program already exists, doing other things, but now additional functionality that uses such a library needs to be added to it? Does that mean that the async/await-based program should be rewritten as a Thread/etc.-based program?
No. You can always just block from an async method. With proper documentation so when you are reusing/maintaining this code a year from now, you don't swear at your past self. :)
If you still spawn your threads, well, yes, it's bad. Because it will not give you any benefit as the thread is still allocated and consuming resources for the specific purpose of running your worker function. Running a few threads to be able to do work in parallel within a service has a minimal impact on your application.
If DoSomething() is synchronous, you could switch to the Timer class instead. It allows multiple timers to use a smaller amount of threads.
If it's important that the jobs can complete, you can modify your worker classes like this:
SemaphoreSlim _shutdownEvent = new SemaphoreSlim(0,1);
public async Task Stop()
{
return await _shutdownEvent.WaitAsync();
}
private void WorkerThreadFunc()
{
while (!shuttingDown)
{
DoSomething();
Thread.Sleep(10);
}
_shutdownEvent.Release();
}
.. which means that during shutdown you can do this:
var tasks = myServices.Select(x=> x.Stop());
Task.WaitAll(tasks);
A thread can only do one thing at a time. While it is working on your DoSomething it can't do anything else.
In an interview Eric Lippert described async-await in a restaurant metaphor. He suggests to use async-await only for functionality where your thread can do other things instead of waiting for a process to complete, like respond to operator input.
Alas, your thread is not waiting, it is doing hard work in DoSomething. And as long as DoSomething is not awaiting, your thread will not return from DoSomething to do the next thing.
So if your thread has something meaningful to do while procedure DoSomething is executing, it's wise to let another thread do the DoSomething, while your original thread is doing the meaningful stuff. Task.Run( () => DoSomething()) could do this for you. As long as the thread that called Task.Run doesn't await for this task, it is free to do other things.
You also want to cancel your process. DoSomething can't be cancelled. So even if cancellation is requested you'll have to wait until DoSomething is completed.
Below is your DoSomething in a form with a Start button and a Cancel button. While your thread is DoingSomething, one of the meaningful things your GUI thread may want to do is respond to pressing the cancel button:
void CancellableDoSomething(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
DoSomething()
}
}
async Task DoSomethingAsync(CancellationToken token)
{
var task = Task.Run(CancellableDoSomething(token), token);
// if you have something meaningful to do, do it now, otherwise:
return Task;
}
CancellationTokenSource cancellationTokenSource = null;
private async void OnButtonStartSomething_Clicked(object sender, ...)
{
if (cancellationTokenSource != null)
// already doing something
return
// else: not doing something: start doing something
cancellationTokenSource = new CancellationtokenSource()
var task = AwaitDoSomethingAsync(cancellationTokenSource.Token);
// if you have something meaningful to do, do it now, otherwise:
await task;
cancellationTokenSource.Dispose();
cancellationTokenSource = null;
}
private void OnButtonCancelSomething(object sender, ...)
{
if (cancellationTokenSource == null)
// not doing something, nothing to cancel
return;
// else: cancel doing something
cancellationTokenSource.Cancel();
}

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

I have the following async long running method inside my asp.net mvc-5 web application :-
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 am using Hangfire tool which support running background jobs to call this async method on timely basis, but un-fortuntly the hangefire tool does not support calling async methods directly . so to overcome this problem i created a sync version of the above method , as follow:-
public void Scan()
{
ScanAsync("test").Wait();
}
then from the HangFire scheduler i am calling the sync method as follow:-
RecurringJob.AddOrUpdate(() => ss.Scan(), Cron.Minutely);
so i know that using .Wait() will mainly occupy the iis thread during the method execution ,, but as i mentioned i need to do it in this way as i can not directly call an async TASK inside the hangefire scheduler .
so what will happen when i use .Wait() to call the async method ?, will the whole method's operations be done in a sync way ? for example as shown above i have three async operations inside the ScanAsync() ;SingleOrDefualtAsync,ToListAsync & SaveChangesAsync, so will they be executed in sync way because i am calling the ScanAsync method using .wait() ?
so what will happen when i use .Wait() to call the async method ?,
will the whole method's operations be done in a sync way ? for example
as shown above i have three async operations inside the ScanAsync()
;SingleOrDefualtAsync,ToListAsync & SaveChangesAsync, so will they be
executed in sync way because i am calling the ScanAsync method using
.wait() ?
The methods querying the database will still be executed asynchronously, but the fact that you're calling Wait means that even though you're releasing the thread, it wont return to the ASP.NET ThreadPool as you're halting it.
This is also a potential for deadlocks, as ASP.NET has a custom synchronization context which makes sure the context of the request is availiable when in a continuation of an async call.
I would recommend that instead, you'd use the synchronous API provided by entity-framework, as you won't actually be enjoying the scalability one can get from asynchronous calls.
Edit:
In the comments, you asked:
As i am currently doing with hangefire eliminate the async effect ? if yes then will it be better to use sync methods instead ? or using sync or async with hangeffire will be exactly the same
First, you have to understand what the benefits of async are. You don't do it because it's cool, you do it because it serves a purpose. What is that purpose? Being able to scale under load. How does it do that? When you await an async method, control is yielded back to the caller. For example, you have an incoming request, you query you database. You can either sit there and wait for the query to finish, or you can re-use that thread to serve more incomong requests. That's the true power.
If you don't actually plan on receiving a decent amount of requests (such that you'll starve the thread-pool), you won't actually see any benefit from async. Currently, the way you've implemented it, you won't see any of those benefits because you're blocking the async calls. All you'll see, possibly, are deadlocks.
This very much depends on the way HangFire is implemented. If it just queuing tasks to be invoked in ThreadPool the only effect will be, that one of your threads will be blocked until the request is ended. However if there is a custom SynchronizationContext this can lead to a serious deadlock.
Consider, if you really want to wait for your scheduled job to be done. Maybe all you want is just a fire and forget pattern. This way your method will be like:
public void Scan()
{
ScanAsync("test"); // smoothly ignore the task
}
If you do need to wait, you can instead try using async void method:
public async void Scan()
{
await ScanAsync("test");
DoSomeOtherJob();
}
There are many controversies about using async void as you cannot wait for this method to end, nor you can handle possible errors.
However, in event driven application this can be the only way. For more informations you can refer to: Async Void, ASP.Net, and Count of Outstanding Operations

Categories