Task is asynchronous or synchronous without async await? - c#

If I have task without async await, will my task consider asynchronous or synchronous? In Microsoft doc, it says The tasks run asynchronously and may complete in any order. but in one stackoverflow post, it says Wait will synchronously block until the task completes. So the current thread is literally blocked waiting for the task to complete.

Task is asynchronous or synchronous without async await?
That depends entirely on the Task itself, and will have nothing to do with whether you use await or not.
When you use Task.Run() to create a new task, that queues a worker to the thread pool, and it will run asynchronously. But, you can also get a Task object from the Task.FromResult() method, which trivially returns a completed task synchronously.
In between those two extremes are things like async methods that sometimes complete synchronously and sometimes don't (e.g. reading data from a file or network, where sometimes the data is already buffered and available and other times it won't be available until later).
The Stack Overflow post you mention doesn't have anything to do with the asynchronous nature of a task, but rather what happens depending on how you wait for the task to complete. Of course, synchronously-completed task objects are already completed by the time you have a reference to the object, so "waiting" on such an object never actually blocks anything. So the interesting case are task objects which are not already completed, i.e. which are going to complete asynchronously.
In those cases, the Wait() method will block the current thread. That's by design, and is clearly documented as such. This is almost never what you want. But it's important to note that even if you use Wait(), the task itself is still asynchronous. You may have blocked the current thread, but other things are still happening in your process, including whatever it is that task represents. Those things are happening asynchronously with your current thread.
The fact that you've chosen to make your current thread do nothing, doesn't change the inherently asynchronous nature of the task you started.
More typically, you will use await to effectively register your request to have the current method resume execution later, in the current synchronization context, once the task completes. At the await statement, the current method will yield the thread back to the caller, allowing it to go on to do other things. In that case, the task is still being completed asynchronously, just as if you'd used Wait() and blocked the thread, but now your current thread also has the opportunity to do something else.
In both cases, the task itself is still asynchronous. The way you've waited on it does not have any effect on that.
IMHO, it makes less sense to worry about whether the task is asynchronous or not. Your code should work the same regardless. Instead, view the task as a "promise" to provide a result at some point in the future. Indeed, the words "promise" and "future" are often used instead of "task" in other programming environments, to represent the same thing. Sometimes that promise is fulfilled immediately, sometimes it takes awhile, but it really doesn't matter to you which happens. What's important is the promise itself, not how or exactly when the promise will be kept.

Related

Is there a neat way to force a pile of `async` C# code to run single-threadly as though it weren't actually `async`

Suppose (entirely hypothetically ;)) I have a big pile of async code.
10s of classes; 100s of async methods, of which 10s are actually doing async work (e.g. where we WriteToDbAsync(data) or we ReadFileFromInternetAsync(uri), or when WhenAll(parallelTasks).
And I want to do a bunch of diagnostic debugging on it. I want to perf profile it, and step through a bunch of it manually to see what's what.
All my tools are designed around synchronous C# code. They will sort of work with async, but it's definitely much less effective, and debugging is way harder, even when I try to directly manage the threads a bit.
If I'm only interested in a small portion of the code, then it's definitely a LOT easier to temporarily un-async that portion of the code. Read and Write synchronously, and just Task.Wait() on each of my "parallel" Tasks in sequence. But that's not viable for to do if I want to poke around in a large swathe of the code.
Is there anyway to ask C# to run some "async" code like that for me?
i.e. some sort of (() => MyAsyncMethod()).RunAsThoughAsyncDidntExist() which knows that any time it does real async communication with the outside world, it should just spin (within the same thread) until it gets an answer. Any time it's asked to run code in parallel ... don't; just run them in series on its single thread. etc. etc.
I'm NOT talking about just awaiting for the Task to finish, or calling Task.Wait(). Those won't change how that Task executes itself
I strongly assume that this sort of thing doesn't exist, and I just have to live with my tools not being well architected for async code.
But it would be great if someone with some expertise in the area, could confirm that.
EDIT: (Because SO told me to explain why the suggestion isn't an answer)...
Sinatr suggested this: How do I create a custom SynchronizationContext so that all continuations can be processed by my own single-threaded event loop? but (as I understand it) that is going to ensure that each time there's an await command then the code after that await continues on the same thread. But I want the actual contents of the await to be on the same thread.
Keep in mind that asynchronous != parallel.
Parallel means running two or more pieces of code at the same time, which can only be done with multithreading. It's about how code runs.
Asynchronous code frees the current thread to do other things while it is waiting for something else. It is about how code waits.
Asynchronous code with a synchronization context can run on a single thread. It starts running on one thread, then fires off an I/O request (like an HTTP request), and while it waits there is no thread. Then the continuation (because there is a synchronization context) can happen on the same thread depending on what the synchronization context requires, like in a UI application where the continuation happens on the UI thread.
When there is no synchronization context, then the continuation can be run on any ThreadPool thread (but might still happen on the same thread).
So if your goal is to make it initially run and then resume all on the same thread, then the answer you were already referred to is indeed the best way to do it, because it's that synchronization context that decides how the continuation is executed.
However, that won't help you if there are any calls to Task.Run, because the entire purpose of that method is to start a new thread (and give you an asynchronous way to wait for that thread to finish).
It also may not help if the code uses .ConfigureAwait(false) in any of the await calls, since that explicitly means "I don't need to resume on the synchronization context", so it may still run on a ThreadPool thread. I don't know if Stephen's solution does anything for that.
But if you really want it to "RunAsThoughAsyncDidntExist" and lock the current thread while it waits, then that's not possible. Take this code for example:
var myTask = DoSomethingAsync();
DoSomethingElse();
var results = await myTask;
This code starts an I/O request, then does something else while waiting for that request to finish, then finishes waiting and processes the results after. The only way to make that behave synchronously is to refactor it, since synchronous code isn't capable of doing other work while waiting. A decision would have to be made whether to do the I/O request before or after DoSomethingElse().

What is the best way to wait for a task to finish with respect to .NET?

This is our async method which executes for a long time in a Task.
public async Task<int> LongRunningMethod(T p1, T p2, T p3);
Some developers in my team use
Task t = Task.Factory.StartNew(LongRunningMethod(p1,p2,p3));
t.Wait(); //This will suspend main thread and wait for 't' to finish.
While some use
await LongRunningMethod(p1,p2,p3);
// Here too, we simply 'await' till the method finishes.
Note: We have a asynchronous task and we want to wait till that task gets completed.
In short, Which one is the best among the above two constructs ?
In short, Which one is the best among the above two constructs ?
You will know the impact, when system scalability comes in the picture, difference between Task.Wait() and await Task is way they treat the calling / executing thread. When the first one would block till the completion happens, other one using await would free up the caller, but mind it only for a True Asynchronous call, which would mean a IO call, Network call, Database call which is not in memory logical processing, and expose Async APIs, that's when calling thread or the context is freed up. For a true Async call, it would use IO completion ports (queuing mechanism) in windows, to execute the Async pipeline.
This would not happen if at the end of the call chain final method is not true Async.
They look almost similar Wait and await
Indeed, for both continuation will execute post completion, but let's take an example, normally threads getting processed are directly linked to the number of cores in the system, using TPL these thread are invoked from a pool and there are limit to number of thread available. For a high scalable system like 100 K / sec requests, Task.Wait() would time out for a long running method very quickly, as threads are busy idling around and blocked and they will not take new request, but for await no such blockage happens at all.
Practical examples
Javascript, NodeJs always go for Async requests by default, no blocking, which is reason why the systems are highly scalable
Also consider ConfigureAwait(false), along with await, then it will not look for same thread context to re-enter for the continuation to execute, which is much more efficient
The point of using Tasks is to execute some Task in parallel from the same context. if you want to start a long running task from a context and just want to wait for the task to finish, both method you showed will work in the same way.
But if you want do any other operation during the execution of the long running task,
you can do as
Task taskObj = LongRunningMethod();
/// Do some other operations here...
var result = await taskObj;
But if need the result from the long running task to do some operation you need to await for the task to complete.
or you can use Task.ContinueWith()

Task.Factory.New vs Task.Run vs async/await, best way to not block UI thread

I need to make sure some of my code runs in the background and doesn't stop block the UI thread, and I thought I knew how to use Task.Factory.New, but as I read more and more, it seems that it doesn't always create a new thread but sometimes runs it on the UI thread if the thread pool thinks that's the way to go so now I am pretty confused over what to use to be safe that the method is not blocking the UI thread. I should also add that I don't need a return value from the method , I just need it to run asynchronously ( in the background ).
So what's the difference between these methods below and what is best to use to make sure it doesn't block the UI thread ?
And is it really true that Task.Factory.StartNew doesn't always create a thread that runs in the background and doesn't block the UI?
public Form1()
{
Task.Factory.StartNew(() => Thread.Sleep(1000));
Task.Run(() => Thread.Sleep(1000));
Task<int> longRunningTask = LongRunningOperationAsync();
}
public async Task<int> LongRunningOperationAsync() // assume we return an int from this long running operation
{
await Task.Delay(1000);
return 1;
}
I should also add that I don't need a return value from the method
Beware of a common problem: just because you don't need a return value doesn't mean you shouldn't await the returned task. awaiting the task provides you with exception information as well. The only time it's appropriate to ignore the returned task is when you don't care about the return value and you don't care about any exceptions the background work may raise (that is, you're OK with silently swallowing them).
In easily >99% of cases, the appropriate behavior is to await the task.
So what's the difference between these methods below
StartNew is an outdated way to run code on a thread pool thread. You should use Run instead of StartNew. I describe why in painful detail on my blog, but the short answer is that StartNew does not understand async delegates and has inappropriate default options.
async is completely different. Run executes code on a thread pool thread, but async rewrites the code so that it doesn't need a thread while there's an asynchronous operation in progress. So, the Run example will block a thread pool thread for 1000ms in the Thread.Sleep call. The async example will run on the UI thread and then not use the UI thread for 1000ms in the await Task.Delay call.
and what is best to use to make sure it doesn't block the UI thread?
Both Task.Run and async are appropriate in UI apps, depending on the nature of the background code.
If your code is asynchronous (usually all I/O-bound code), then you should use async/await. Note that imposing asynchrony "top-down" is hard. Don't think about "forcing code off the UI thread"; instead, identify the naturally-asynchronous parts of your system (DB, file, WebAPI calls, etc), change them to be async at the lowest level, and work up from there.
If your code is synchronous (CPU-bound), then you can use Task.Run if it takes too long to run on your UI thread.
And is it really true that Task.Factory.StartNew doesn't always create a thread that runs in the background and doesn't block the UI?
Run always executes code on threads from the thread pool. The rules for StartNew are much more complex, but in your example example code, if TaskScheduler.Current == TaskScheduler.Default, then StartNew will also use a thread from the thread pool.
The two examples you give are pretty much the same and depend of the context you are using them on.
Tasks are a way to describe a packet of work with meta information to know about its state, synchronize multiple tasks, cancel them etc. The main idea about tasks and asynchronicity is that you don't have to care about "where" (on which thread) this unit of work is executed, it is performed asynchronously, that's all you need to know. So no worries for your UI-Thread, as long as you are working asynchronously, it won't be locked (that's one of the main improvements since Win8 and the async/await keywords, every UI Manipulation has to be async not to bloat the UI).
As for async&await, those are in fact syntactic sugar. In many simple cases, you don't need to care about the task itself, you just want the asynchronous computation "do this and give me the answer when you have it".
int x = await ComputeXAsync(); //Returns a Task<int> which will be automatically unwrapped as an int
If you need to synchronize tasks, for example start multiple tasks in parallel and wait that all of them are done before continuing, you can't rely on the simple await Task<int> format, you then need to work with the task itself, its Status property and in this case the Task.WaitAll(task[]) API.
Edit: I really recommend the chapter of JonSkeets Book C# in Depth (last edition). The Async/Await part is really well explained and will take you way further than any reading online will do.
The first two are actually the same. see here
Well you can think of it as a task is something you want to be done.
A thread is something like a worker which does the task for you. So basically a threads helps you doing a task, but it doesn't return a value.
a task does not create its own OS thread. Instead, tasks are executed by a TaskScheduler; the default scheduler simply runs on the ThreadPool.
See Here
An example is. A remote request you can do as task, you want the job done but dont know when it will be. But a TCPListener for the server I would run as a thread, because it always needs to listen to the socket.
Like Andreas Niedermair pointed out, you can also use longliving tasks with the TaskCreationOptions

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.

Is it possible for two tasks to run simultaneously on the same thread in C#?

I am not sure how C# works when assigning tasks to thread.
I want to verify something. Is it guaranteed that at any time, each task is being handled by one and only one thread, regardless of what that task is doing, even if its just stopped or did Thread.currentThread().sleep(), that thread will not go and serve any other task ? So its 1:1 between the thread and the tasks ? Regardless of what the task is doing, even if its just sleeping, or whether the task was called via Task.Run or await Task.Run etc ?
There are a couple of cases I'm aware of where tasks can be re-entrant. One is where one task is waiting for another task to complete, and that first task hasn't yet started. It makes sense for the new task to be started on the current thread in that case... sort of. It does raise some nasty worries about locking and any other thread-local context.
It's also possible (apparently) for Task.Factory.StartNew to execute a new task "inline", if the scheduler deems it appropriate - but the schedulers built into .NET don't do this.
See this other Stack Overflow question which includes more detailed response from Stephen Toub (on the PFX team).

Categories

Resources