Async in Asp.net MVC/WebAPI - asp.net

Using of Async and Await keyword is encourged in the recent conf with MS , If i use a Await keyword that can span a new thread in which the code will execute In which case what will happen to Asp.net Worker thread. Will it wait for the request to complete or will continue to serve other request .

await does not spawn a new thread. See my async/await intro post or the async/await FAQ.
However, you can spawn a new task by explicitly calling Task.Run, if you want to.
When you call await, if the object you're awaiting is not already complete, then await will schedule the remainder of your async method to run later, and the current thread is returned to the thread pool. No threads are used by async or await while the asynchronous operation is in progress. When the asynchronous operation completes, the remainder of the async method runs on a thread pool thread (which may or may not be the same thread it started on). This is not normally a problem because in the common case (1), the async method resumes in the correct request context.
(1) The common case is that await is awaiting a Task or Task<TResult> directly.

Related

Task.run takes two threads in an asp .net request?

Service layer
public async Task<string> getAllAsync()
{
return await WCFMethodAsync();
}
Presentation layer
public class Customer : Controller
{
public async Task<string> Index()
{
var r = await Task.Run(getAllAsync());
return r;
}
}
I will describe what I think is happening. I would like to know if I am wrong.
the request takes a thread from ThreadPool
await returns an incomplete Task
Task.Run queues a Task to run getAllAsync
3.1. that will take a thread from the ThreadPool.
when the getAllAsync method finishes the taken thread returns to the group of threads
when the service method call end .net is notified and a thread is taken from the group of threads o terminate the request.
Where is the incomplete homework returned to? Since the method was executed inside Task.Run.
I would like to know the flow of the whole process.
Since a thread was initially taken from the thread group and task.run takes a work thread, the question is when the task ends the job (wcf) and a thread is taken to finish the request. How many threads were used to process the request?
Your getAllAsync method is a I/O bound operation, because you are making a network call to reach your WCF service instance.
That means the getAllAsync will be executed by the network driver. It is an asynchronous non-blocking promise task. The calling thread is not blocked until the asynchronous I/O operation finishes. When it finishes the ThreadPool will be notified about it.
On the other hand the Task.Run is design for CPU bound operation.
The Task.Run returns a delegate task and it is used to queue a work on the ThreadPool. That work will be processed by one of the CPU core.
So if you put an asynchronous I/O work (kick-off) call on a dedicated Thread then that is just wasting valuable resources.

Should I use async/await in Hangfire job ?

I recently started using Hangfire to handle my background jobs in an ASP.NET project.
My jobs are involving lots, lots (and lots) of HTTP calls using WebRequest (I may migrate to something else, but that's for later).
While browsing SO on this subject, I stumbled upon people who do async calls in hangfire.
Is there any point in using async/await tasks inside a Hangfire job ? I'm aware that it is a queue, so jobs won't execute concurrently, but since my project has no GUI, is there any reason I would use async/await to do my HTTP calls inside a Hangfire job ?
PS : The requests that are involving a long-running job use the Task "design pattern", so clients won't experience any timeout
You can absolutely use Hangfire to run async methods, and use awaits within those async methods.
The SO question you linked to was making a blocking Wait call on the method passed to Hangfire to be serialized and then later executed by the hangfire service.
This is very different from something like
hangfireClient.Enqueue(() => myClass.RunAsync());
where RunAsync is an async method that contains awaits.
public async Task<bool> RunAsync() {
//do your work
var subJob = new worker();
return await subJob.DoWork();
}

Why 'await' cannot be used in ordinary functions?

Correction: as follows from two answers, the problem looks to be specific to dart as C# implements Task.Wait allowing to achieve the desired effect. I would be grateful for any further information on the reasons why this is not possible in dart or how to achieve it there. I would be happy to close the question in its current form.
There are situations where it could make sense to have synchronous functions use asynchronous calls internally waiting for their completion before delivering the result. This is explicitly not allowed in both C# and Dart: anything that uses await must be marked as async (thus returning a future).
A simple example in Dart, but the same is valid for C#:
Disclaimer: this is not how I would do things, so do not suggest a "correct" solution of converting all methods to async; the code here is just to illustrate the question.
I have a fully asynchronous implementation of a generic wrapper for HTTP requests to some particular REST API. It does some login, authentication etc.:
class RequestProcessor {
Future post(String path, [payload]) async {
return request("POST", path, payload);
}
}
I would like to implement a high-level user-facing API translating to requests to the REST-API. Some of those methods I'd like to have synchronous. This is what I would like and am not allowed to have:
class API {
final RequestProcessor processor;
API(this.processor);
// this takes long and should be asynchronous, happy with a future (OK)
Future getQueryResults(query) async {
return await processor.post("/query", query);
}
// here I would prefer to have it synchronous (COMPILE ERROR)
String getVersion() {
return await processor.post("/version");
}
}
Question: Why is this not allowed?
It's a design choice.
Dart is single-threaded - each synchronous function call will run to completion before allowing any other code to run. If you allow a synchronous function to block until a future is complete, then no other code will run and the future will never complete (because the code that would complete it can't run).
It is possible to have a system that allows other code to run while one synchronous function is blocked. That requires either having more than one active stack (parallel or not), or implicitly transforming the entire program to be async. Neither choice is great when you compile to JavaScript, so Dart did not try to do that.
The await is an asynchronous wait so it does not make sense to have it in a synchronous function. To be asynchronous the method needs to return when the awaited operation is initiated, whereas the synchronous method needs to run to completion.
You can use a synchronous wait instead, in which case your method does not need to be async. In C# you can do this by calling the Wait() method on the returned task.
Because waiting and returning a future is fundamentally different.
Returning a future frees the current thread and optionally schedules a continuation for later, waiting blocks the current thread.
For example, in a UI thread, returning a future is fine but waiting will cause the UI to hang, in a web server thread waiting will block the thread and prevent the web server from handling more request, etc.
It's even possible waiting for what should be an async operation will cause a deadlock.
.net provide Task.Wait for when you know waiting is fine, I don't know about dart - but this is not automatic (except for await inside catch clauses in async methods in C#)
In Dart marking a function/method async tells the VM that it needs to rewrite the code before executing it.
await doesn't change an async function to a sync one, the function is still async, it just allows nicer syntax than then(() { return ...then(() { return...})}) chains.
If you make an async call everything following is async, there is nothing you can do about it.

ASP.NET and async - how it works?

I know that is a common question, but I've read a kiloton of articles and feel confused. And now I think that it would be better not to read them at all )).
So, how ASP.NET works (only about threads):
http request is served by thread from the thread pool.
while request is processing this thread is busy, because request is processing inside exactly this thread.
when request processing finishes, the thread returns to thread pool, server sends a response.
Is this described behaviour right ?
What really happens when I start new task inside ASP.NET MVC controller?
public ActionResult Index()
{
var task1 = Task.Factory.StartNew(() => DoSomeHeavyWork());
return View();
}
private static async Task DoSomeHeavyWork()
{
await Task.Delay(5000);
}
controller action starts to execute inside thread that processes current request - T1.
the thread pool allocates another one thread (T2) for task1.
task1 starts "immediately" inside T2.
the View result returns "immediately".
ASP.NET do some work, server sends a response, T1 returns to the thread pool, T2 is still alive.
after some time when the DoSomeHeavyWork will be finished, the T2 thread will be returned to the thread pool.
Is it correct ?
Now lets look to async action
public async Task<ActionResult> Index()
{
await DoSomeHeavyWork();
return View();
}
, I understand the difference with previous code sample, but not the process, in this example the behaviour is the following:
action starts to execute inside thread that processes current request - T1.
DoSomeHeavyWork "immediately" returns a task, let's call it "task1" too.
T1 returns to the thread pool.
after the DoSomeHeavyWork finishes, Index action continue to execute.
after Index action execution the server will send a response.
Please explain what happening between points 2 and 5, the questions are:
is the DoSomeHeavyWork processed inside task1 or where (where it is "awaited") ? I think this a key question.
which thread will continue to process the request after await - any new one from the thread pool, right ?
request produces thread allocating from the thread pool, but response will not be sent until the DoSomeHeavyWorkAsync finished and it doesn't matter in which thread this method executes. In other words, according to single request and single concrete task (DoSomeHeavyWork) there is no benefits of using async. Is it correct ?
if the previous statement is correct, then I don't understand how the async can improve performance for multiple requests with the same single task. I'll try to explain. Let's assume that the thread pool has 50 threads available to handle requests. Single request should be processed at least by one single thread from the thread pool, if the request starts another threads, then all of them will be taken from the thread pool, e.g. request takes one thread to process himself, starts 5 different tasks in parallel and wait all of them, thread pool will have 50 - 1 - 5 = 44 free threads to handle incoming requests - so this is a parallelism, we can improve performance for single request, but we reduce number of requests which can be processed. So according request processing in ASP.NET I suppose that only task that somehow starts IO completion thread can achieve a goal of async (TAP). But how IO completion thread calls back thread pool thread in this case ?
Is this described behaviour right ?
Yes.
Is it correct ?
Yes.
is the DoSomeHeavyWork processed inside task1 or where (where it is
"awaited") ? I think this a key question.
From the current code, DoSomeHeavyWork will asynchronously wait for Task.Delay to complete. Yes, this will happen on the same thread allocated by the thread-pool, it won't spin any new threads. But there isn't a guarantee that it will be the same thread, though.
which thread will continue to process the request after await?
Because we're talking about ASP.NET, that will be an arbitrary thread-pool thread, with the HttpContext marshaled onto it. If this was WinForms or WPF app, you'd be hitting the UI thread again right after the await, given that you don't use ConfigureAwait(false).
request produces thread allocating from the thread pool, but response
will not be sent until the DoSomeHeavyWorkAsync finished and it
doesn't matter in which thread this method executes. In other words,
according to single request and single concrete task (DoSomeHeavyWork)
there is no benefits of using async. Is it correct ?
In this particular case, you won't see the benefits of async. async shines when you have concurrent requests hitting the server, and alot of them are doing IO bound work. When using async while hitting the database, for example, you gain freeing the thread-pool thread for the amount of time the query executes, allowing the same thread to process more requests in the meanwhile.
But how IO completion thread calls back thread pool thread in this
case ?
You have to separate parallelism and concurrency. If you need computation power for doing CPU bound work in parallel, async isn't the tool that will make it happen. On the other hand, if you have lots of concurrent IO bound operations, like hitting a database for CRUD operations, you can benefit from the usage of async by freeing the thread while to IO operation is executing. That's the major key point for async.
The thread-pool has dedicated pool of IO completion threads, as well as worker threads, which you can view by invoking ThreadPool.GetAvailableThreads. When you use IO bound operations, the thread that retrieves the callbacks is usually an IO completion thread, and not a worker thread. They are both have different pools.

Why wasn't the synchronous action executed until the asynchronous action completed?

I'm implementing Comet in ASP.NET MVC. I used a timer to keep an async request in the server. The async request will complete when the timer elapses after 1 minute and sends a response to the client (to avoid 404 error) and then reconnects to Async Controller.
I also want to execute some synchronous actions while the async request was holding, but the problem is:
When an async action was executed and hold by using timer, the sync action wasn't called until the async action (Comet long-live request) completed.
I did the test with Firefox 3.6 many times, but the result is always the same; it is so strange. Do you know why?
I have a sub-question:
To implement Comet, using a timer (response after some minutes elapsed) or thread (response after several time sleeping thread) to hold async request; which is better?
I found the answer for my problems.
First,the reason why Sync action wasn't executed while Async action holding because session request block mechanic, Asp.net session block request so that all requests will be process one by one even you use concurrent request with Ajax Async Call. And the solution is disable session on controller you want to hold long-live request. Here is detail explanation: https://blogs.msdn.com/b/rickandy/archive/2009/12/17/session-less-mvc-controller.aspx
The second, when perform holding long-live request,using timer and thread sleeping are NOT different, because Asp.net thread pool will essentially create new thread to track time elapsed and call back to your timer elapsed event. It will decrease number of threads to serve request in thread pool because it born new thread to track timer event.

Resources