stevie
stevie

Reputation: 249

C# async tasks: do all participating methods have to be async as well?

When we are dealing with async tasks, the task consists of multiple method calls (possibly of other classes) which in turn consist of yet further method calls. We could call this a tree. Do all methods have to be of type async task for the original task to truly behave async? Would the answer be true for any kind of background task of other similar languages, mostly Java as well? (In C#, once I had one of my methods somewhere in this tree get into an infinite loop (talk about a long running task!), yet sadly, the original async task's isRunning property returned false.)

Upvotes: 4

Views: 3231

Answers (5)

DvS
DvS

Reputation: 1095

The short answer is no. Async means that work being done by another process can be handed off to that process and so not block the calling thread. All the better if those processes don’t reside on the same machine, since that work will occupy very little compute or IO at the caller. This is achieved by suspending method execution using the async/await mechanism, which promises to resume on some synchronisation context once completed. So, why the overview?

Because this means that we can and should judiciously choose those operations that should be async, and so apply the await keyword in an async method. Some won’t need it, since they are lightweight and adding async to them may even add compute time to them, due to the creation of the async state machine. So the operations in a method can often be a mixture of asynchronous and synchronous code.

And this in turn means that some methods would use the Task return type with async/await, and some will be regular, synchronous methods.

Upvotes: 2

CookedCthulhu
CookedCthulhu

Reputation: 787

No, they don't have to. Simple example, in a Forms application this

button.Click += async (_, __) =>
                {
                    await Task.Run(() => MyClass.SomeTimeconsumingMethod());
                };

still lets you move the window during the execution of SomeTimeconsumingMethod, whereas this one

button.Click += (_, __) =>
                {
                    MyClass.SomeTimeconsumingMethod();
                };

doesn't let you do it.

Upvotes: 1

Stephen Cleary
Stephen Cleary

Reputation: 457402

Do all methods have to be of type async task for the original task to truly behave async?

In order to behave asynchronously, an async method must have an await statement for an operation that is not already completed.

I think my async intro blog post would be helpful for you.

Would the answer be true for any kind of background task of other similar languages, mostly Java as well?

Yes.

sadly, the original async task's isRunning property returned false

I assume you mean that the TaskStatus was not TaskStatus.Running. This is normal and expected, since asynchronous tasks are Promise Tasks, not Delegate Tasks (see my blog for more info).

Upvotes: 4

Dennis
Dennis

Reputation: 37800

Do all methods have to be of type async task for the original task to truly behave async

It depends on what do you mean by "all" word.

Some APIs must not be asynchronous. Think about List<T>.Add, for example. Do you really want it to be asynchronous?
Some APIs should be asynchronous, but there's no asynchronous counterpart (e.g. SMO, or File static class).

Ideally you should do "async all the way", when talking about IO-bound operations. But IRL you can face with violation of this rule, when some part of your async method chain will execute IO-bound operation synchronously.

Upvotes: 0

Gusdor
Gusdor

Reputation: 14322

The only requirement for using the await keyword is that the method you are awaiting returns a Task or Task<T>.

The exact implementation of this method (async or return someTask) has no influence on the correctness of the code, although it may influence the function.

Any normal code can run in an async method alongside your await calls. The only significant restriction is that out and ref are not allowed.

Upvotes: 0

Related Questions