Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# async/await for I/O-Bound vs CPU-Bound operation

I am learning about asynchronous programming in C#. In this article I found that for IO-Bound operations you should not use Task.Run() but I don't know how to create a task without Task.Run()... For example I want to create a custom method named GetPageCountAsync, which query database and return results. I have method GetPageCount already which query database synchronous. I don't know better way than:

private async Task<int> GetPageCountAsync()
{
  return await Task.Run(() => GetPageCount());
}

How to do this without Task.Run? I found a ExecuteReaderAsync method of SqlCommand class but I wonder how is this method implemented? Without Task.Run? If so, how?

like image 867
Klemenko Avatar asked Feb 05 '18 14:02

Klemenko


People also ask

What do you mean by C?

C is a structured, procedural programming language that has been widely used both for operating systems and applications and that has had a wide following in the academic community. Many versions of UNIX-based operating systems are written in C.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.

What is C language used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

Why is CA procedural language?

C is an imperative procedural language supporting structured programming, lexical variable scope, and recursion, with a static type system. It was designed to be compiled to provide low-level access to memory and language constructs that map efficiently to machine instructions, all with minimal runtime support.


2 Answers

It is the responsibility of whatever framework you're using to perform the IO operation to provide an inherently asynchronous operation to you. It can either provide a method returning a Task, or some other asynchronous operation (i.e. a method that takes a callback, returns an IAsyncResult, fires an event, etc.) that can be turned into a Task.

If the operation you're calling already synchronously blocks the thread until the asynchronous result has completed, then it's already too late. Most DB frameworks are good about providing some form of asynchronous way of querying the database, so odds are another method is out there for you to use. If you're using a framework that doesn't provide any asynchronous version of the method, then there's no way for you to avoid using multiple threads; the author(s) of the framework have taken that choice out of your hands.

like image 89
Servy Avatar answered Oct 06 '22 02:10

Servy


To make your method async all you have to do is await an asynchronous operation within it, and make the method signature like this (Assuming the return value here...):

async Task<int> GetPageCountAsync()
{
    //not shown is how to set up your connection and command
    //nor disposing resources
    //nor validating the scalar value
    var pages = await command.ExecuteScalarAsync().ConfigureAwait(false);
    return (int)pages;
}

If you have no async methods to call in the libraries you are using you can create your own awaitables but it should be extremely rare you need to go to such lengths.

Now that GetPageCountAsync is async you simply await it:

return await GetPageCountAsync();

It is also good practice for non-context aware code such as this to allow the code to resume on another context like:

return await GetPageCountAsync().ConfigureAwait(false);

If you have other work to do, not dependent on the result of the query, you can start it and await it later to perform work in parallel:

 Task pageCountTask = GetPageCountAsync();
//do something not dependent on page count....
return await pageCountTask;
like image 20
Crowcoder Avatar answered Oct 06 '22 04:10

Crowcoder