Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use C# async/await for CPU-bound tasks [closed]

I'm getting the hang of the async/await keywords in C#, and how they facilitate asynchronous programming - allowing the the thread to be used elsewhere whilst some I/O bound task like a db call is going on.

I have read numerous times that async/await is for I/O bound tasks, not CPU-bound tasks. CPU-bound tasks should be performed on a separate background thread. Mentioned several times in these videos. All ok.

However, when starting long-running CPU-bound work on a new thread using Task.Run, you then have to await it at some point. So aren't we using async/await here for a CPU-bound task too? See example below.

public async Task SomeMethodAsync()
{
    int result = await Task.Run(() =>
    {
        // Do lots of CPU bound calculations...

        return result;
    }

    // Then do something with the result.
}
like image 507
Tophat Gordon Avatar asked Feb 22 '18 13:02

Tophat Gordon


People also ask

Why do we use %d in C?

In C programming language, %d and %i are format specifiers as where %d specifies the type of variable as decimal and %i specifies the type as integer. In usage terms, there is no difference in printf() function output while printing a number using %d or %i but using scanf the difference occurs.

What is C used for today?

It is used in developing an operating system. Operating systems such as Apple's OS X, Microsoft's Windows, and Symbian are developed using 'C' language. It is used for developing desktop as well as mobile phone's operating system. It is used for compiler production.

What are the main uses of C++?

Introduction to Uses of C++ 1 Uses of C++. There are several benefits of using C++ for developing applications and many applications product based developed in this language only because of its features and security. 2 Conclusion – Uses of C++. ... 3 Recommended Articles: This has been a guide to Uses of C++ in the real world. ...

Why should I learn C programming?

‘C’ programming is the basic foundation of the other programming languages. If you learn C programming now then later it will play an essential role while learning other programming languages. It gives the same ideas, such as control statements, operators, data types, and many more.

Why do we prefer uses of C #over other languages?

Why prefer uses of C# over other languages. It holds the advantages for code length and code clarity. This brings our decision which gives us an understanding of the right language and platform to choose for the underlying product development. No language is good or bad it all depends upon the exact need and purpose.

Why is C used for embedded system programming?

You may not know but they have a CPU with them which do need programming and the software's written for them are known as embedded system programs. These programs have to be fast in execution but also have a very little memory. No question why C is ideally suited for embedded system programming.


2 Answers

async/await is the contemporary and easiest way to do async programming whether or not the job is I/O-bound; whether or not the Task requires a thread.

For example, it is great for WinForms or WPF because the main thread can await a child task to calculate the number of times Miss Piggy had lunch in a year (a rather long and complex CPU-bound operation let's say) and when complete executes the next line immediately below. It makes your code so intuitive unlike classical async callbacks; WaitOnes or other mechanisms and the juggling acts that go with it.

MSDN:

You can avoid performance bottlenecks and enhance the overall responsiveness of your application by using asynchronous programming. However, traditional techniques for writing asynchronous applications can be complicated, making them difficult to write, debug, and maintain.

Visual Studio 2012 introduces a simplified approach, async programming, that leverages asynchronous support in the .NET Framework 4.5 and the Windows Runtime. The compiler does the difficult work that the developer used to do, and your application retains a logical structure that resembles synchronous code. More...

OP:

I have read numerous times that async/await is for I/O bound tasks

Incorrect. async/await is shorthand for async programming where the compiler does more of the work. It is not just for I/O-bound tasks. CPU-bound tasks generally use a thread pool thread.

CPU-bound tasks should be performed on a separate background thread.

Yes...but that doesn't mean you can't await the Task. CPU-bound tasks unlike I/O-bound tasks require a thread to operate and by definition a worker thread and so will grab one from the available thread pool.

However, when starting long-running CPU-bound work on a new thread using Task.Run, you then have to await it at some point

You don't have to await a Task, such tasks would be known as fire-and-forget. The await doesn't actually start it either, tasks are "hot". However by not awaiting, you run the risk of the task not completing when the application exits. e.g. a console app firing off a Task and not awaiting it then exiting.

So aren't we using async/await here for a CPU-bound task too?

That's right, you can use it for any Task whether it is I/O-bound or not.

More

  • What if not await the task?
  • Async and await
like image 190
MickyD Avatar answered Sep 24 '22 11:09

MickyD


If you await for something you have a promise that you will get results from that awaited operation. Normally you expect that awaited operation is asynchronous\background operation which will be executed in the future. In the meanwhile you can continue with your work which can be done independently from the result of that operation.

async/await does exactly that it is compiler help to archive that. await will return the control to the caller and process awaited operation asynchronously. That asynchronism could be provided in different ways.

I/O operations will be processed asynchronously once they are in kernel space, so you don't need to create additional thread for I/O operations.

After the System API call, the request is now in kernel space, making its way to the networking subsystem of the OS (such as /net in the Linux Kernel). Here the OS will handle the networking request asynchronously. Details may be different depending on the OS used (the device driver call may be scheduled as a signal sent back to the runtime, or a device driver call may be made and then a signal sent back), but eventually the runtime will be informed that the networking request is in progress. At this time, the work for the device driver will either be scheduled, in-progress, or already finished (the request is already out "over the wire") - but because this is all happening asynchronously, the device driver is able to immediately handle something else!

On the other hand for CPU operation you have to instruct somehow CPU to do the stuff asynchronously and typically this is done from different thread(the reason you have Task.Run).

CPU-bound async code is a bit different than I/O-bound async code. Because the work is done on the CPU, there's no way to get around dedicating a thread to the computation. The use of async and await provides you with a clean way to interact with a background thread and keep the caller of the async method responsive. Note that this does not provide any protection for shared data. If you are using shared data, you will still need to apply an appropriate synchronization strategy.

The point is that in both cases you have to await in order to wait for a promise to be fulfilled.

like image 42
Johnny Avatar answered Sep 24 '22 11:09

Johnny