Is async and await exclusively for GUI-based asynchronous programming? - c#

I've been reading about the new async and await operators in C# and tried to figure out in which circumstances they would possibly be useful to me. I studied several MSDN articles and here's what I read between the lines:
You can use async for Windows Forms and WPF event handlers, so they can perform lengthy tasks without blocking the UI thread while the bulk of the operation is being executed.
async void button1_Click(object sender, EventArgs e)
{
// even though this call takes a while, the UI thread will not block
// while it is executing, therefore allowing further event handlers to
// be invoked.
await SomeLengthyOperationAsync();
}
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
In other words, if you create a thread with an ordinary good old ThreadStart entry point (or a Console application with good old static int Main(string[] args)), then you cannot use async and await because at one point you would have to use await, and make the method that uses it async, and hence in the calling method you also have to use await and make that one async and so on. But once you reach the thread entry point (or Main()), there's no caller to which an await would yield control to.
So basically you cannot use async and await without having a GUI that uses the standard WinForms and WPF message loop. I guess all that makes indeed sense, since MSDN states that async programming does not mean multithreading, but using the UI thread's spare time instead; when using a console application or a thread with a user defined entry point, multithreading would be necessary to perform asynchronous operations (if not using a compatible message loop).
My question is, are these assumptions accurate?

So basically you cannot use async and await without having a GUI that uses the standard WinForms and WPF message loop.
That's absolutely not the case.
In Windows Forms and WPF, async/await has the handy property of coming back to the UI thread when the asynchronous operation you were awaiting has completed, but that doesn't mean that's the only purpose to it.
If an asynchronous method executes on a thread-pool thread - e.g. in a web service - then the continuation (the rest of the asynchronous method) will simply execute in any thread-pool thread, with the context (security etc) preserved appropriately. This is still really useful for keeping the number of threads down.
For example, suppose you have a high traffic web service which mostly proxies requests to other web services. It spends most of its time waiting for other things, whether that's due to network traffic or genuine time at another service (e.g. a datbase). You shouldn't need lots of threads for that - but with blocking calls, you naturally end up with a thread per request. With async/await, you'd end up with very few threads, because very few requests would actually need any work performed for them at any one point in time, even if there were a lot of requests "in flight".
The trouble is that async/await is most easily demonstrated with UI code, because everyone knows the pain of either using background threads properly or doing too much work in the UI thread. That doesn't mean it's the only place the feature is useful though - far from it.
Various server-side technologies (MVC and WCF for example) already have support for asynchronous methods, and I'd expect others to follow suit.

A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
Not true - methods marked async just mean they can use await, but callers of those methods have no restrictions. If the method returns Task or Task<T> then they can use ContinueWith or anything else you could do with tasks in 4.0
A good non-UI example is MVC4 AsyncController.
Ultimately, async/await is mostly about getting the compiler rewriting so you can write what looks like synchronous code and avoid all the callbacks like you had to do before async/await was added. It also helps with the SynchronizationContext handling, useful for scenarios with thread affinity (UI frameworks, ASP.NET), but even without those, it's still useful. Main can always do DoStuffAsync().Wait(); for instance. :)

My question is, are these assumptions accurate?
No.
You can use async for Windows Forms and WPF event handlers, so they can perform lengthy tasks without blocking the UI thread while the bulk of the operation is being executed.
True. Also true for other UI applications including Silverlight and Windows Store.
And also true for ASP.NET. In this case, it's the HTTP request thread that is not blocked.
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
This is a best practice ("async all the way down"), but it's not strictly required. You can block on the result of an asynchronous operation; many people choose to do this in Console applications.
an ordinary good old ThreadStart entry point
Well... I do have to take issue with "ordinary good old". As I explain on my blog, Thread is pretty much the worst option you have for doing background operations.
I recommend you review my introduction to async and await, and follow up with the async / await FAQ.

async-await is only wrapper for Task class manipulations, which is part of so named Tasks Parallel Library - TPL(published before async-await auto code generation tech.)
So fact is you may not use any references to UI controls within async - await.
Typically async-await is powerfull tool for any web and server relations, loading resources, sql. It works with smart waiting data with alive UI.
Typically TPL application: from simple big size loop till multi stages parallel calculations in complex calculations based on shared data (ContinueWith and so on)

Related

When you await on async call--is it really asynchronous programming in C#

I have three tier .net web api application. each tier is implementing a async method. Each call is async and and we are using await at each step. My question is when you await at every step, doesn't it make the application synchronous & defeats the purpose ? What value async await really provides? Does it automatically uses multiple CPU cores?
Controller:
public async Task<IHttpActionResult> Get()
{
return Ok(await _service.Create());
}
middle tier:
public async Task<MyObject> Create()
{
return await _repository.CreateAsync(new MyDataObject());
}
DB
public async Task<T> CreateAsync(T data)
{
var o = _dbSet.Add(data);
await _dbContext.SaveChangesAsync();
return 100;
}
In your example you're definitely doing asynchronous processing. What you're not doing is parallel processing. The .NET documentation doesn't always do a good job of differentiating between the two. I'll just cover asynchronous here.
The main idea behind async / await (which your examples do well) is to not have a thread sitting around doing nothing when it could be doing something useful.
Take your CreateAsync example:
public async Task<T> CreateAsync(T data)
{
var o = _dbSet.Add(data);
await _dbContext.SaveChangesAsync();
return 100;
}
The database changes won't happen any faster because of the await. So what's the benefit? For the sake of argument assume the following:
Your app has 5 users
Your app has 2 threads available (way low, but play along)
Each database save takes 3 seconds
Now assume User A and User B save a record at the same time. Each has their own thread (that's a fact, not an assumption). If you aren't using await then users A and B will hold both of your available threads for 3 seconds just waiting for the save to complete. No more threads are available, so users C, D and E will be blocked for that period.
When you use await, the threads are released because they're just... waiting. Now they can take care of users C, D, and E. When the save completes the threads will come back for users A and B and finish the CreateAsync method.
Bottom line, when async / await is done properly n threads can fulfill way more than n requests.
This is a simplified explanation, but I really wish I'd gotten a simple explanation way back when. I hope this helps.
What value async await really provides?
It allows your web server to process more requests at the same time; async/await allows the threads to do other work while the code waits for the db to do its work (db or cache, email service, external api call, etc.).
From Async Programming : Introduction to Async/Await on ASP.NET:
(...) let’s say the requests in the system depend on some external resource, like a database or Web API. When a request comes in, ASP.NET takes one of its thread pool threads and assigns it to that request. Because it’s written synchronously, the request handler will call that external resource synchronously. This blocks the request thread until the call to the external resource returns.
...
Asynchronous request handlers operate differently. When a request comes in, ASP.NET takes one of its thread pool threads and assigns it to that request. This time the request handler will call that external resource asynchronously. This returns the request thread to the thread pool until the call to the external resource returns.
When you await an async method in C#, it does not necessarily mean that the method is executed asynchronously. It simply means that the calling method will be suspended until the awaited task completes.
The async and await keywords in C# are used to simplify the process of writing asynchronous code. They allow you to write code that looks and reads like synchronous code, while still being asynchronous under the hood.
To understand how async and await work, it is important to know that an async method actually returns a Task or Task object, which represents the asynchronous operation. The await operator is used to suspend the execution of the calling method until the awaited Task completes.
However, just because a method is marked async does not necessarily mean that it will be executed asynchronously. The actual execution of the method depends on how the Task is implemented and whether it is running on a thread pool thread or not.
For example, if the Task is running on a ThreadPool thread, it will be executed asynchronously. On the other hand, if the Task is implemented using the Task.Run method, it will be executed synchronously on a separate ThreadPool thread.
In short, the async and await keywords in C# allow you to write asynchronous code that is easier to read and maintain, but they do not guarantee that the code will be executed asynchronously.
Each call is async and and we are using await at each step. My question is when you await at every step, doesn't it make the application synchronous & defeats the purpose?
First of all, synchronous and asynchronous is a property of a method or an execution flow, not a property of the application as a whole. In your case you await on every level and every step all asynchronous operations (Tasks) that you start, so the execution flow of each web request is asynchronous. It's still a single execution flow though. The code is executed in a sequential/serialized fashion. In the context of a single web request, no concurrency is happening.
The difference from a classic and familiar synchronous execution flow is that the flow is not forced to run on the same thread from start to finish. Different threads might be involved in the execution, but not more than one thread at the same time. A thread-switch might occur at each await point, and whether it will happen depends on various factors that might not be under your direct control. The most interesting aspect of an asynchronous flow is that, time-wise, large parts of the execution are usually not running on any thread. For example while the _dbContext.SaveChangesAsync() is doing its job, there is no thread in your process that is blocked waiting for this work to be done. This means that your web application can have a large number of concurrent executions flows (web requests), using only a small number of threads. Which eventually results in increased scalability for your application: you can serve more users with less hardware.
Relatively new developers who come to asynchronous programming directly using async/await may have this confusion. To understand and appreciate the value of what async/await brings to table, one has to go slightly back in time and review how asynchronous code was written then.
Before the keywords were introduced in C#, asynchronous programming was still possible. Traditionally (.NET Framework 2.0 later), there were two patterns:
Event-based Asynchronous Pattern (EAP), where you subscribed to an event:
o.ReadCompleted += (o, e) => { // asynchronously called after ReadAsync completion };
o.ReadAsync(buffer, count); // begin the async process
Task-based Asynchronous Pattern (TAP), which is Promise like interface where you can setup completions with then and catch.
o.ReadAsync(buffer, count)
.then( (result) => { // asynchronously called after ReadAsync completion } );
So, advantage of asynchronous programming on the server is that the calling thread is not blocked on the Read, which is now an asynchronous call as against a synchronous call. The thread can do some other tasks / or serve other requests.
When I/O bound Read eventually completes, the completion delegate will be called, possibly over a different thread. This way there are more threads available which makes the service more scalable. This is advantage of asynchronous programming.
However, the two patterns above have a disadvantage for the developer that the code becomes unreadable and inside-out because it is not written sequentially.
The async/await keywords just let us keep the same advantages of asynchronous programming, while making the code readable.
Now we just write:
var result = await o.ReadAsync(buffer, count);
// here comes code that we had to previously write inside the completion delegate
// but now its more readable, and much natural to handle exceptions
So although it looks sequential to developer it is still asynchronous. The compiler converts the async method into a state machine which behaves similar to code previously written, but hides away all the complex details from the developer. Similar to the completion delegate behavior, the code written after await could also be resumed on a different thread.

Is it pointless to use Threads inside Tasks in C#?

I know the differences between a thread and a task., but I cannot understand if creating threads inside tasks is the same as creating only threads.
It depends on how you use the multithreaded capabilities and the asynchronous programming semantics of the language.
Simple facts first. Assume you have an initial, simple, single-threaded, and near empty application (that just reads a line of input with Console.ReadLine for simplicity sake). If you create a new Thread, then you've created it from within another thread, the main thread. Therefore, creating a thread from within a thread is a perfectly valid operation, and the starting point of any multithreaded application.
Now, a Task is not a thread per se, but it gets executed in one when you do Task.Run which is selected from a .NET managed thread pool. As such, if you create a new thread from within a task, you're essentially creating a thread from within a thread (same as above, no harm done). The caveat here is, that you don't have control of the thread or its lifetime, that is, you can't kill it, suspend it, resume it, etc., because you don't have a handle to that thread. If you want some unit of work done, and you don't care which thread does it, just that's it not the current one, then Task.Run is basically the way to go. With that said, you can always start a new thread from within a task, actually, you can even start a task from within a task, and here is some official documentation on unwrapping nested tasks.
Also, you can await inside a task, and create a new thread inside an async method if you want. However, the usability pattern for async and await is that you use them for I/O bound operations, these are operations that require little CPU time but can take long because they need to wait for something, such as network requests, and disk access. For responsive UI implementations, this technique is often used to prevent blocking of the UI by another operation.
As for being pointless or not, it's a use case scenario. I've faced situations where that could have been the solution, but found that redesigning my program logic so that if I need to use a thread from within a task, then what I do is to have two tasks instead of one task plus the inner thread, gave me a cleaner, and more readable code structure, but that it's just personal flair.
As a final note, here are some links to official documentation and another post regarding multithreaded programming in C#:
Async in Depth
Task based asynchronous programming
Chaining Tasks using Continuation Tasks
Start multiple async Tasks and process them as they complete
Should one use Task.Run within another Task
It depends how you use tasks and what your reason is for wanting another thread.
Task.Run
If you use Task.Run, the work will "run on the ThreadPool". It will be done on a different thread than the one you call it from. This is useful in a desktop application where you have a long-running processor-intensive operation that you just need to get off the UI thread.
The difference is that you don't have a handle to the thread, so you can't control that thread in any way (suspend, resume, kill, reuse, etc.). Essentially, you use Task.Run when you don't care which thread the work happens on, as long as it's not the current one.
So if you use Task.Run to start a task, there's nothing stopping you from starting a new thread within, if you know why you're doing it. You could pass the thread handle between tasks if you specifically want to reuse it for a specific purpose.
Async methods
Methods that use async and await are used for operations that use very little processing time, but have I/O operations - operations that require waiting. For example, network requests, read/writing local storage, etc. Using async and await means that the thread is free to do other things while you wait for a response. The benefits depend on the type of application:
Desktop app: The UI thread will be free to respond to user input while you wait for a response. I'm sure you've seen some programs that totally freeze while waiting for a response from something. This is what asynchronous programming helps you avoid.
Web app: The current thread will be freed up to do any other work required. This can include serving other incoming requests. The result is that your application can handle a bigger load than it could if you didn't use async and await.
There is nothing stopping you from starting a thread inside an async method too. You might want to move some processor-intensive work to another thread. But in that case you could use Task.Run too. So it all depends on why you want another thread.
It would be pointless in most cases of everyday programming.
There are situations where you would create threads.

C# async/await - UI thread vs. other threads [duplicate]

I've been reading about the new async and await operators in C# and tried to figure out in which circumstances they would possibly be useful to me. I studied several MSDN articles and here's what I read between the lines:
You can use async for Windows Forms and WPF event handlers, so they can perform lengthy tasks without blocking the UI thread while the bulk of the operation is being executed.
async void button1_Click(object sender, EventArgs e)
{
// even though this call takes a while, the UI thread will not block
// while it is executing, therefore allowing further event handlers to
// be invoked.
await SomeLengthyOperationAsync();
}
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
In other words, if you create a thread with an ordinary good old ThreadStart entry point (or a Console application with good old static int Main(string[] args)), then you cannot use async and await because at one point you would have to use await, and make the method that uses it async, and hence in the calling method you also have to use await and make that one async and so on. But once you reach the thread entry point (or Main()), there's no caller to which an await would yield control to.
So basically you cannot use async and await without having a GUI that uses the standard WinForms and WPF message loop. I guess all that makes indeed sense, since MSDN states that async programming does not mean multithreading, but using the UI thread's spare time instead; when using a console application or a thread with a user defined entry point, multithreading would be necessary to perform asynchronous operations (if not using a compatible message loop).
My question is, are these assumptions accurate?
So basically you cannot use async and await without having a GUI that uses the standard WinForms and WPF message loop.
That's absolutely not the case.
In Windows Forms and WPF, async/await has the handy property of coming back to the UI thread when the asynchronous operation you were awaiting has completed, but that doesn't mean that's the only purpose to it.
If an asynchronous method executes on a thread-pool thread - e.g. in a web service - then the continuation (the rest of the asynchronous method) will simply execute in any thread-pool thread, with the context (security etc) preserved appropriately. This is still really useful for keeping the number of threads down.
For example, suppose you have a high traffic web service which mostly proxies requests to other web services. It spends most of its time waiting for other things, whether that's due to network traffic or genuine time at another service (e.g. a datbase). You shouldn't need lots of threads for that - but with blocking calls, you naturally end up with a thread per request. With async/await, you'd end up with very few threads, because very few requests would actually need any work performed for them at any one point in time, even if there were a lot of requests "in flight".
The trouble is that async/await is most easily demonstrated with UI code, because everyone knows the pain of either using background threads properly or doing too much work in the UI thread. That doesn't mean it's the only place the feature is useful though - far from it.
Various server-side technologies (MVC and WCF for example) already have support for asynchronous methods, and I'd expect others to follow suit.
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
Not true - methods marked async just mean they can use await, but callers of those methods have no restrictions. If the method returns Task or Task<T> then they can use ContinueWith or anything else you could do with tasks in 4.0
A good non-UI example is MVC4 AsyncController.
Ultimately, async/await is mostly about getting the compiler rewriting so you can write what looks like synchronous code and avoid all the callbacks like you had to do before async/await was added. It also helps with the SynchronizationContext handling, useful for scenarios with thread affinity (UI frameworks, ASP.NET), but even without those, it's still useful. Main can always do DoStuffAsync().Wait(); for instance. :)
My question is, are these assumptions accurate?
No.
You can use async for Windows Forms and WPF event handlers, so they can perform lengthy tasks without blocking the UI thread while the bulk of the operation is being executed.
True. Also true for other UI applications including Silverlight and Windows Store.
And also true for ASP.NET. In this case, it's the HTTP request thread that is not blocked.
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
This is a best practice ("async all the way down"), but it's not strictly required. You can block on the result of an asynchronous operation; many people choose to do this in Console applications.
an ordinary good old ThreadStart entry point
Well... I do have to take issue with "ordinary good old". As I explain on my blog, Thread is pretty much the worst option you have for doing background operations.
I recommend you review my introduction to async and await, and follow up with the async / await FAQ.
async-await is only wrapper for Task class manipulations, which is part of so named Tasks Parallel Library - TPL(published before async-await auto code generation tech.)
So fact is you may not use any references to UI controls within async - await.
Typically async-await is powerfull tool for any web and server relations, loading resources, sql. It works with smart waiting data with alive UI.
Typically TPL application: from simple big size loop till multi stages parallel calculations in complex calculations based on shared data (ContinueWith and so on)

Use of async/await in console or web apps

As I understand it, the async/await feature in C# splits up the segments between await calls into callback methods that run on the calling thread after each awaited method has returned on a separate worker thread. The calling thread is "free" during the waiting time. The callback must be scheduled on the calling thread through some sort of event loop.
This event loop only exists in GUI applications like Windows Forms or WPF. Freeing this loop makes sure the UI remains responsive for other user interaction during long operations.
Console apps and web apps (ASP.NET) do not have such event loops, so this callback mechanism doesn't work. But then again, they do not have an event loop because they don't need one. There is no user trying to interact with the running program at any time, expecting immediate feedback. So there's no need to free the calling thread for that. It doesn't matter how many threads the operation uses, it only returns after the last bit is done.
So what's the use of async and await in console and web apps, or any kind of non-interactive code in general, like for example Windows services? How is that different or more efficient compared to simple synchronous calls?
I'm designing an API that is used by GUI and non-interactive (service and web) programs and have a hard time understanding how it behaves in non-GUI environments.
The point with async-await is that the calling thread is always freed up when you reach the first asynchronous point (i.e. the first await of an uncompleted task).
In UI apps you have a SynchronizationContext that posts the code after the awaits to the UI thread because code that interacts with the UI must be executed by the UI thread otherwise you'll get an exception. You can control that by using ConfigureAwait(false).
In console apps (and services, etc.) there's no such need, so that code runs on some ThreadPool thread. The calling thread (which is likely to be also a ThreadPool thread) was freed up and was able to do other kinds of work in the meantime instead of blocking synchronously. So async-await improves scalability as it enables doing more work with the same amount of threads.
i3arnon's answer is (as usual) excellent.
So what's the use of async and await in console and web apps, or any kind of non-interactive code in general, like for example Windows services?
The primary benefit of async on the client side is responsiveness; the primary benefit of async on the server side is scalability.
How is that different or more efficient compared to simple synchronous calls?
Client-side responsiveness and server-side scalability are achieved by the same mechanism: freeing up the calling thread. Thus, async is all about using fewer threads. On the server side, using fewer threads allows your app to make maximum use of the existing threadpool.
As I understand it, the async/await feature in C# splits up the segments between await calls into callback methods that run on the calling thread after each awaited method has returned on a separate worker thread.
This is why I'm answering. I just can't let this one go. Every time "thread" is mentioned in this understanding, it's wrong. This part is correct: await does "split up" an async method into segments.
1) The callback methods are not run on the calling thread. Rather, await will capture a "context" and resume the method on that context. On ASP.NET apps and Console apps in particular, the context does not imply a particular thread. I explain how await captures context in detail on my async intro blog post.
2) Async APIs are not normally executed on worker threads. The entire point of async is to free up threads, so blocking thread pool threads wouldn't make sense. I explain how asynchronous I/O is almost threadless in my blog post on There Is No Thread.
Async / await has nothing to do with multi threading, to quote MSDN:
The async and await keywords don't cause additional threads to be
created. Async methods don't require multithreading because an async
method doesn't run on its own thread.
Async / await allows you to structure your code with regards to long running operations (could be CPU work or I/O work). So this is applicable to any type of program (GUI, Web Service, console etc)

Calling await on a task created with Task.Run()

Why is it possible to do this in C#?
var task = Task.Run (...);
await task;
Isn't Task.Run() supposed to be used for CPU-bound code? Does it make sense to call awaitfor this?
I.e., after calling Task.Run I understand that the task is running in another thread of the thread pool. What's the purpose of calling await? Wouldn't make more sense just to call task.Wait()?
One last question, my first impression was that await is intended to be used exclusively with async methods. Is it common to use it for task returned by Task.Run()?
EDIT. It also makes me wonder, why do we have Task.Wait () and not a Task.Await(). I mean, why a method is used for Wait() and a keyworkd for await. Wouldn't be more consistent to use a method in both cases?
There would be no point at all in using Wait. There's no point in starting up a new thread to do work if you're just going to have another thread sitting there doing nothing waiting on it. The only sensible option of those two is to await it. Awaiting a task is entirely sensible, as it's allowing the original thread to continue execution.
It's sensible to await any type of Task (in the right context), regardless of where it comes from. There's nothing special about async methods being awaited. In fact in every single asynchronous program there needs to be asynchronous methods that aren't using the async keyword; if every await is awaiting an async method then you'll never have anywhere to start.
There are several good answers here, but from a more philosophical standpoint...
If you have lots of CPU-bound work to do, the best solution is usually the Task Parallel Library, i.e., Parallel or Parallel LINQ.
If you have I/O-bound work to do, the best solution is usually async and await code that is built around naturally-asynchronous implementations (e.g., Task.Factory.FromAsync).
Task.Run is a way to execute a single piece of CPU-bound code and treat it as asynchronous from the point of view of the calling thread. I.e., if you want to do CPU-bound work but not have it interfere with the UI.
The construct await Task.Run is a way to bridge the two worlds: have the UI thread queue up CPU-bound work and treat it asynchronously. This is IMO the best way to bridge asynchronous and parallel code as well, e.g., await Task.Run(() => Parallel.ForEach(...)).
why a method is used for Wait() and a keyword for await.
One reason that await is a keyword is because they wanted to enable pattern matching. Tasks are not the only "awaitables" out there. WinRT has its own notion of "asynchronous operations" which are awaitable, Rx observable sequences are awaitable, Task.Yield returns a non-Task awaitable, and this enables you to create your own awaitables if necessary (e.g., if you want to avoid Task allocations in high-performance socket applications).
Yes, it's common and recommended. await allows to wait for a task (or any awaitable) asynchronously. It's true that it's mostly used for naturally asynchronous operations (e.g. I/O), but it's also used for offloading work to be done on a different thread using Task.Run and waiting asynchronously for it to complete.
Using Wait not only blocks the calling thread and so defeats the purpose of using Task.Run in the first place, it could also potentially lead to deadlocks in a GUI environment with a single threaded synchronization context.
One last question, my first impression was that await is intended to be used exclusively with async methods
Whether a method is actually marked with the async modifier is an implementation detail and most "root" task returning methods in .Net aren't actually async ones (Task.Delay is a good example for that).
Wouldn't make more sense just to call task.Wait()?
No, if you call Wait you're involving two threads there, one of the worker threads from the ThreadPool is working for you (given the task is CPU bound), and also your calling thread will be blocked.
Why would you block the calling thread? The result will be too bad if the calling thread is a UI thread! Also if you call Task.Run immediately followed by Task.Wait you're making it worse, too. It is no better than calling the delegate synchronously. There is no point whatsoever in calling Wait immediately after starting a Task.
You should almost never use Wait, always prefer await and release the calling thread.
It is very common and useful for cases like (greatly simplified; production code would need exception handling, for instance):
async void OnButtonClicked()
{
//... Get information from UI controls ...
var results = await Task.Run(CpuBoundWorkThatShouldntBlockUI);
//... Update UI based on results from work run in the background ...
}
Regarding the comment of your later edit, 'await' is not a method call. It is a keyword (only allowed in a method that has been marked 'async', for clarity) that the compiler uses to decide how to implement the method. Under the hood, this involves rewriting the method procedure as a state machine that can be paused every time you use the 'await' keyword, then resumed when whatever is it awaiting calls back to indicate that it is done. This is a simplified description (exception propagation and other details complicate things), but the key point is that 'await' does a lot more than just calling a method on a Task.
In previous C# versions, the closest construct to this 'async/await' magic was the use of 'yield return' to implement IEnumerable<T>. For both enumerations and async methods, you want a way to pause and resume a method. The async/await keywords (and associated compiler support) start with this basic idea of a resumable method, then add in some powerful features like automatic propagation of exceptions, dispatching callbacks via a synchronization context (mostly useful to keep code on the UI thread) and automatic implementation of all the glue code to set up the continuation callback logic.

Categories

Resources