Should I wrap slow calls with Task.Run? - c#

I have this ASP MVC call which is aync because of an async call it needs to make. I noticed there are a couple of slow sync calls (e.g. db access). The method needs to have all returned data available in order to proceed.
I thought of wrapping the sync calls with Task.Run and await for all of them.
Does it make sense to wrap the slow sync calls? What if there was only sync calls?

Don't use Task.Run to parallelize work in the server-side code, unless the number of client requests you expect to serve concurrently is really low. Otherwise, you might speed up the processing of an individual request, but you'll hurt scalability of your web app for when there are many users.

To try and extend #Noseratio, spinning up thread to "speed up" sync work scales terribly bad.
An important thing to remember is that using Task.Run inside ASP.NET is extremely dangerous because the runtime isn't aware you queued work which needs to be done and IIS may attempt to recycle you app from time to time which will cause work to abrupt unintentionally.
If you're using .NET Framework 4.5.2 there is a solution via HostingEnvironment.QueueBackgroundWorkItem. You can read more about it in Fire and Forget on ASP.NET. If not, read Returning Early from ASP.NET Requests for a custom implementation. Both of these excellent articles are by #StephanCleary

If the tasks are independent (don't depend on data from the other tasks), and can be performed independently, then yes, by all means execute them asynchronously. If they're Entity Framework, and it's version 6 then it offers Async methods to call, and you don't have to wrap them in Task.Run.
Even if the tasks aren't independent, you may still be able to order them in a way to make them more efficient when executed.
Whether or not to use Task.Run, however is an important distinction. Task.Run will use a ThreadPool thread, which if it's doing something synchronous will block, and therefore reduce the number of ThreadPool theads available to your application. If you have many users, and you are executing many tasks, this could be a problem.
Try to find async api's rather than using Task.Run.

Related

How do a library provide async methods if it is a bad practice to do Task.Run?

In this article: https://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html , it is advised against using Task.Run. however there are lot of libraries that provide methods that ends with Async and hence I expect those methods to return a running task that I can await (which however is not necessary, since those libraries could decide to return a synchronous task).
The context is a ASP.NET application. How am I supposed to make a method running in parallel?
What I understand is that async calls are executed in parallel if they contain at least one "await" operator inside, the problem is that the innermost call, should be parallel to achieve that, and to do that I have somewhat to resort to Task.Run
I have also seen some examples using TaskCompletionSource, is this necessary to implement the "inner most async method" to run a method in parallel in a ASP.NET application?
In an ASP.Net application we tend to value requests/s over individual response times1 - certainly if we're directly trading off one versus the other. So we don't try to focus more CPU power at satisfying one request.
And really, focussing more CPU power at a task is what Task.Run is for - it's for when you have a distinct chunk of work to be done, you can't do it on the current thread (because its got its own work to do) and when you're free to use as much CPU as possible.
In ASP.Net, where async shines is when we're dealing with I/O. Nasty slow things like accessing the file system or talking to a database across the network. And wonderfully, at the lowest level, the windows I/O system is async already and we don't have to devote a thread just to waiting for things to finish.
So, you won't be using Task.Run. Instead you'll be looking for I/O related objects that expose Async methods. And those methods themselves will not, as above, be using Task.Run. What this does allow us to do is to stop using any threads for servicing our particular request whilst there's no work to be done, and so improve out requests/s metric.
1This is a generalization but single user/request ASP.Net sites are rare in my experience.

When should I use Async Controllers in ASP.NET MVC?

I have some concerns using async actions in ASP.NET MVC. When does it improve performance of my apps, and when does it not?
Is it good to use async action everywhere in ASP.NET MVC?
Regarding awaitable methods: shall I use async/await keywords when I want to query a database (via EF/NHibernate/other ORM)?
How many times can I use await keywords to query the database asynchronously in one single action method?
You may find my MSDN article on the subject helpful; I took a lot of space in that article describing when you should use async on ASP.NET, not just how to use async on ASP.NET.
I have some concerns using async actions in ASP.NET MVC. When it improves performance of my apps, and when - not.
First, understand that async/await is all about freeing up threads. On GUI applications, it's mainly about freeing up the GUI thread so the user experience is better. On server applications (including ASP.NET MVC), it's mainly about freeing up the request thread so the server can scale.
In particular, it won't:
Make your individual requests complete faster. In fact, they will complete (just a teensy bit) slower.
Return to the caller/browser when you hit an await. await only "yields" to the ASP.NET thread pool, not to the browser.
First question is - is it good to use async action everywhere in ASP.NET MVC?
I'd say it's good to use it everywhere you're doing I/O. It may not necessarily be beneficial, though (see below).
However, it's bad to use it for CPU-bound methods. Sometimes devs think they can get the benefits of async by just calling Task.Run in their controllers, and this is a horrible idea. Because that code ends up freeing up the request thread by taking up another thread, so there's no benefit at all (and in fact, they're taking the penalty of extra thread switches)!
Shall I use async/await keywords when I want to query database (via EF/NHibernate/other ORM)?
You could use whatever awaitable methods you have available. Right now most of the major players support async, but there are a few that don't. If your ORM doesn't support async, then don't try to wrap it in Task.Run or anything like that (see above).
Note that I said "you could use". If you're talking about ASP.NET MVC with a single database backend, then you're (almost certainly) not going to get any scalability benefit from async. This is because IIS can handle far more concurrent requests than a single instance of SQL server (or other classic RDBMS). However, if your backend is more modern - a SQL server cluster, Azure SQL, NoSQL, etc - and your backend can scale, and your scalability bottleneck is IIS, then you can get a scalability benefit from async.
Third question - How many times I can use await keywords to query database asynchronously in ONE single action method?
As many as you like. However, note that many ORMs have a one-operation-per-connection rule. In particular, EF only allows a single operation per DbContext; this is true whether the operation is synchronous or asynchronous.
Also, keep in mind the scalability of your backend again. If you're hitting a single instance of SQL Server, and your IIS is already capable of keeping SQLServer at full capacity, then doubling or tripling the pressure on SQLServer is not going to help you at all.
Asynchronous action methods are useful when an action must perform several independent long running operations.
A typical use for the AsyncController class is long-running Web
service calls.
Should my database calls be asynchronous ?
The IIS thread pool can often handle many more simultaneous blocking requests than a database server. If the database is the bottleneck, asynchronous calls will not speed up the database response. Without a throttling mechanism, efficiently dispatching more work to an overwhelmed database server by using asynchronous calls merely shifts more of the burden to the database. If your DB is the bottleneck, asynchronous calls won’t be the magic bullet.
You should have a look at 1 and 2 references
Derived from #PanagiotisKanavos comments:
Moreover, async doesn't mean parallel. Asynchronous execution frees a
valuable threadpool thread from blocking for an external resource, for
no complexity or performance cost. This means the same IIS machine can
handle more concurrent requests, not that it will run faster.
You should also consider that blocking calls start with a
CPU-intensive spinwait. During stress times, blocking calls will
result in escalating delays and app pool recycling. Asynchronous calls
simply avoid this
is it good to use async action everywhere in ASP.NET MVC?
As usual in programming, it depends. There is always a trade-off when going down a certain path.
async-await shines in places where you know you'll receiving concurrent requests to your service and you want to be able to scale out well. How does async-await help with scaling out? In the fact that when you invoke a async IO call synchronously, such as a network call or hitting your database, the current thread which is responsible for the execution is blocked waiting for the request to finish. When you use async-await, you enable the framework to create a state machine for you which makes sure that after the IO call is complete, your method continues executing from where it left off.
A thing to note is that this state machine has a subtle overhead. Making a method asynchronous does not make it execute faster, and that is an important factor to understand and a misconception many people have.
Another thing to take under consideration when using async-await is the fact that it is async all the way, meaning that you'll see async penetrate your entire call stack, top to buttom. This means that if you want to expose synchronous API's, you'll often find yourself duplicating a certain amount of code, as async and sync don't mix very well.
Shall I use async/await keywords when I want to query database (via
EF/NHibernate/other ORM)?
If you choose to go down the path of using async IO calls, then yes, async-await will be a good choice, as more and more modern database providers expose async method implementing the TAP (Task Asynchronous Pattern).
How many times I can use await keywords to query database
asynchronously in ONE single action method?
As many as you want, as long as you follow the rules stated by your database provider. There is no limit to the amount of async calls you can make. If you have queries which are independent of each other and can be made concurrently, you can spin a new task for each and use await Task.WhenAll to wait for both to complete.
async actions help best when the actions does some I\O operations to DB or some network bound calls where the thread that processes the request will be stalled before it gets answer from the DB or network bound call which you just invoked. It's best you use await with them and it will really improve the responsiveness of your application (because less ASP input\output threads will be stalled while waiting for the DB or any other operation like that). In all my applications whenever many calls to DB very necessary I've always wrapped them in awaiatable method and called that with await keyword.
My 5 cents:
Use async/await if and only if you do an IO operation, like DB or external service webservice.
Always prefer async calls to DB.
Each time you query the DB.
P.S. There are exceptional cases for point 1, but you need to have a good understanding of async internals for this.
As an additional advantage, you can do few IO calls in parallel if needed:
Task task1 = FooAsync(); // launch it, but don't wait for result
Task task2 = BarAsync(); // launch bar; now both foo and bar are running
await Task.WhenAll(task1, task2); // this is better in regard to exception handling
// use task1.Result, task2.Result
As you know, MVC supports asynchronous controllers and you should take advantage of it. In case your Controller, performs a lengthy operation, (it might be a disk based I/o or a network call to another remote service), if the request is handled in synchronous manner, the IIS thread is busy the whole time. As a result, the thread is just waiting for the lengthy operation to complete. It can be better utilized by serving other requests while the operation requested in first is under progress. This will help in serving more concurrent requests.
Your webservice will be highly scalable and will not easily run into C10k problem.
It is a good idea to use async/await for db queries. and yes you can use them as many number of times as you deem fit.
Take a look here for excellent advise.
My experience is that today a lot of developers use async/await as a default for controllers.
My suggestion would be, use it only when you know it will help you.
The reason is, as Stephen Cleary and others already mentioned, it can introduce performance issues, rather than resolving them, and it will help you only in a specific scenario:
High-traffic controllers
Scalable backend
Is it good to use async action everywhere in ASP.NET MVC?
It's good to do so wherever you can use an async method especially when you have performance issues at the worker process level which happens for massive data and calculation operations. Otherwise, no need because unit testing will need casting.
Regarding awaitable methods: shall I use async/await keywords when I
want to query a database (via EF/NHibernate/other ORM)?
Yes, it's better to use async for any DB operation as could as possible to avoid performance issues at the level of worker processes.
Note that EF has created many async alternatives for most operations, such as:
.ToListAsync()
.FirstOrDefaultAsync()
.SaveChangesAsync()
.FindAsync()
How many times can I use await keywords to query the database
asynchronously in one single action method?
The sky is the limit

Async-Await vs ThreadPool vs MultiThreading on High-Performance Sockets (C10k Solutions?)

I'm really confused about async-awaits, pools and threads. The main problem starts with this question: "What can I do when I have to handle 10k socket I/O?" (aka The C10k Problem).
First, I tried to make a custom pooling architecture with threads
that uses one main Queue and multiple Threads to process all
incoming datas. It was a great experience about understanding
thread-safety and multi-threading but thread is an overkill
with async-await nowadays.
Later, I implemented a simple architecture with async-await but I
can't understand why "The async and await keywords don't cause
additional threads to be created." (from MSDN)? I think there
must be some threads to do jobs like BackgroundWorker.
Finally, I implemented another architecture with ThreadPool and it
looks like my first custom pooling.
Now, I think there should be someone else with me who confused about handling The C10k. My project is a dedicated (central) server for my game project that is hub/lobby server like MCSG's lobbies or COD's matchmaking servers. I'll do the login operations, game server command executions/queries and information serving (like version, patch).
Last part might be more specific about my project but I really need some good suggestions about real world solutions about multiple (heavy) data handling.
(Also yes, 1k-10k-100k connection handling depending on server hardware but this is a general question)
The key point: Choosing Between the Task Parallel Library and the ThreadPool (MSDN Blog)
[ADDITIONAL] Good (basic) things to read who wants to understand what are we talking about:
Threads
Async, Await
ThreadPool
BackgroundWorker
async/await is roughly analogous to the "Serve many clients with each thread, and use asynchronous I/O and completion notification" approach in your referenced article.
While async and await by themselves do not cause any additional threads, they will make use of thread pool threads if an async method resumes on a thread pool context. Note that the async interaction with ThreadPool is highly optimized; it is very doubtful that you can use Thread or ThreadPool to get the same performance (with a reasonable time for development).
If you can, I'd recommend using an existing protocol - e.g., SignalR. This will greatly simplify your code, since there are many (many) pitfalls to writing your own TCP/IP protocol. SignalR can be self-hosted or hosted on ASP.NET.
No. If we use asynchronous programming pattern that .NET introduced in 4.5, in most of the cases we need not to create manual thread by us. The compiler does the difficult work that the developer used to do. Creating a new thread is costly, it takes time. Unless we need to control a thread, then “Task-based Asynchronous Pattern (TAP)” and “Task Parallel Library (TPL)” is good enough for asynchronous and parallel programming. TAP and TPL uses Task. In general Task uses the thread from ThreadPool(A thread pool is a collection of threads already created and maintained by .NET framework. If we use Task, most of the cases we need not to use thread pool directly. A thread can do many more useful things. You can read more about Thread Pooling
You can avoid performance bottlenecks and enhance the overall responsiveness of your application by using asynchronous programming. Asynchrony is essential for activities that are potentially blocking, such as when your application accesses the web. Access to a web resource sometimes is slow or delayed. If such an activity is blocked within a synchronous process, the entire application must wait. In an asynchronous process, the application can continue with other work that doesn't depend on the web resource until the potentially blocking task finishes.
Await is specifically designed to deal with something taking time, most typically an I/O request. Which traditionally was done with a callback when the I/O request was complete. Writing code that relies on these callbacks is quite difficult, await greatly simplifies it. Await just takes care of dealing with the delay, it doesn't otherwise do anything that a thread does. The await expression, what's at the right of the await keyword, is what gets the job done. You can use Async with any method that returns a Task. The XxxxAsync() methods are just precooked ones in the .NET framework for common operations that take time. Like downloading data from a web server.
I would recommend you to read Asynchronous Programming with Async and Await

Using Task.WaitAll in a WCF method

I have a .NET 4.5.1 WCF service that handles synchronization from an app that will be used by thousands of users. I currently use Task.WaitAll as shown below and it works fine but I read that this is bad, can cause deadlocks, etc. I believe I tried WhenAll in the past and it didn't work, I don't recall the issues as I'm returning to this for review again just to make sure I'm doing this right. My concern is whether or not the blocking is needed and preferred in this use, a WCF service method hence why the WaitAll appears to work without issue.
I have about a dozen methods that each update an entity in Entity Framework 6 processing the incoming data with existing data and making the necessary changes. Each of these methods can be expensive so I would like to use parallelism mainly to get all methods working at the same time on this powerful 24 core server. Each method returns as Task as wraps its contents in Task.Run. The DoSync method created a new List and adds each of these sync methods to the list. I then call Task.WaitAll(taskList.ToArray()) and all works great.
Is this the right way of doing this? I want to make sure this method will scale well, not cause problems, and work properly in a WCF service scenario.
In high-scale services it is often a good idea to use async IO (which you are not - you use Task.Run). "High scale" is very loosely defined. The benefit of async IO on the server is that it does not block threads. This leads to less memory usage and less context switching. That is all there is to it.
If you do not need these benefits you can use sync IO and blocking all you like. Nothing bad will happen. Understand, that running 10 queries on background threads and waiting for them will temporarily block 11 threads. This might be fine, or not, depending on the number of concurrent operations you expect.
I suggest you do a little research regarding the scalability benefits of async IO so that you better understand when to use it. Remember that there is a cost to going async: Slower development and more concurrency bugs.
Understand, that async IO is different from just using the thread-pool (Task.Run). The thread-pool is not thread-less while async IO does not use any threads at all. Not even "invisible" threads managed by the runtime.
What I often find is: If you have to ask, you don't need it.
Task.WhenAll is the non-blocking equivalent of Task.WaitAll, and without seeing your code I can't think of any reason why it wouldn't work and wouldn't be preferable. But note that Task.WhenAll itself returns a Task which you must await. Did you do that?

Choosing Between WF CodeActivity and AsyncCodeActivity for DB Operations

I'm still fairly new to WF so bear with me if I don't get this worded correctly the first time. ;)
If you're doing selects against a well-normalized database, using primary keys, returning single records, in a fairly low volume environment (a few hundred requests per day), does it really make a difference whether you use CodeActivity vs AsyncCodeActivity?
While I've got some additional research to do on hosting and execution, it will be possible, but not probable, for multiple requests to be received at or near the same time. I'm not sure if that will change the answer or not.
Thanks!
Microsoft used non async in their ExecuteSqlQuery activity: http://wf.codeplex.com/releases/view/43585
Async Activities:
"This is useful for custom activities that must perform asynchronous work without holding the workflow scheduler thread and blocking any activities that may be able to run in parallel."
"As a result of going asynchronous, an AsyncCodeActivity may induce an idle point during execution. Due to the volatile nature of asynchronous work, an AsyncCodeActivity always creates a no persist block for the duration of the activity’s execution. This prevents the workflow runtime from persisting the workflow instance in the middle of the asynchronous work, and also prevents the workflow instance from unloading while the asynchronous code is executing."
Source: http://msdn.microsoft.com/en-us/library/ee358731.aspx
Edit: I noticed that only pointed out the disadvantages of using async I would consider the responses of Ron and Tim to make a better decision
In general I strongly encourage activity developers who are doing any kind of I/O to use AsyncCodeActivity and to call the underlying Async APIs whenever possible. Even if the query is short this is always preferrable.
Obviously - it's not going to make a difference unless you're actually calling an Async API inside your activity implementation.
That said, even if it makes a difference it might not make a noticeable difference in many apps. Potential reasons:
The query just runs too fast.
You aren't running multiple queries in parallel. (Running many async operations in parallel is faster than doing them synchronously and thereby sequentially.)
You don't run a large number of workflows in parallel such as would be needed to experience thread contention.

Categories