If you need to wait for the method asynchronously, then you need to set await , which in turn requires the async modifier.

And so there is a chain of methods with the async modifier, which somehow catches the eye and it seems that something is not right here.

The question is:

The "pyramid" of async modifiers is normal, or may someday you have to wait for the result via wait ?

  • "Pyramid" of async modifiers is fine - Grundy

2 answers 2

 "ΠŸΠΈΡ€Π°ΠΌΠΈΠ΄Π°" ΠΈΠ· async ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠ²- это Π½ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½ΠΎ? 

Yes

 ΠΈΠ»ΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΊΠΎΠ³Π΄Π°-Π½ΠΈΠ±ΡƒΠ΄ΡŒ ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΎΠ²Π°Ρ‚ΡŒΡΡ синхронно Π΄ΠΎΠΆΠ΄Π°Ρ‚ΡŒΡΡ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° Ρ‡Π΅Ρ€Π΅Π· wait? 

This can happen when the calling code does not support asynchrony, for example

  • if you gradually transfer your code from synchronous to asynchronous (that is, not all calls support async),
  • support old interfaces,
  • if the calling code is in a third-party bibioteca
  • or you use asynchronous methods in getters / setters (which is not recommended).

But in general, using .Wait() , .Result , GetAwaiter().GetResult() is considered not very good practice , this should be treated with caution.

    I would say, not a pyramid , but a chain .

    The chain of asynchronous calls is not just normal: the only way an asynchronous code should be.

    Normal threads, when you suspend them to wait for the end of an I / O operation, will simply take up resources. If there are 1000 calls to your web server at the same time and you send 1000 requests to the database, you will have exactly 1000 threads stopped. For each thread, the OS will allocate 1 MB of RAM, and the thread scheduler will take into account each of them, which will slow down the speed of the system as a whole.

    Instead, Windows offers special threads: sleepy . Such a thread sleeps, but can be awakened by the system when it is necessary to process the result of an I / O operation. After processing the result, the thread falls asleep again.

    Processing the results should not be very difficult. Usually this is something quite simple: received a sample from the database, generated HTML and gave it to the client. With this approach, the number of threads can be very small, for example, for the same 1000 clients, 10 threads may be enough, because most of the time they expect a response from the database, and when it is received, they quickly generate HTML and are ready to process the next answer.

    The requirement of simple processing is very important. If you delay the flow with your processing, the task scheduler will have to create a new thread.

    Simple processing is: 1. Fast calculations. If you need to count for a long time, try counting in parallel, or transfer processing to a background process. 1. No thread synchronization. No semaphores, mutexes, monitors, and more. The stream waiting for a signal will be in a normal sleep state, but in a non-sensitive state. 1. No waiting for I / O operations. Such a stream will also sleep the usual sleep.

    That is why async methods need to be chained. In essence, this will mean that from the deepest method in the code there is only waiting for I / O and simple processing of the results.

    If the last method in the chain is very simple and does not contain an I / O operation, you can use Task.CompletedTask or Task.FromResult .

    • ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠΈ: Ρ‡ΡƒΡ‚ΠΊΠΎ спящиС can read about it somewhere? - tym32167
    • Π’Ρ€Π΅Π±ΠΎΠ²Π°Π½ΠΈΠ΅ простой ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ β€” ΠΎΡ‡Π΅Π½ΡŒ Π²Π°ΠΆΠ½ΠΎΠ΅. Если Π²Ρ‹ Π·Π°Π΄Π΅Ρ€ΠΆΠΈΡ‚Π΅ ΠΏΠΎΡ‚ΠΎΠΊ своСй ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ, Ρ‚ΠΎ ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΡƒ Π·Π°Π΄Π°Ρ‡ придётся ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ Π½ΠΎΠ²Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Π’Ρ€Π΅Π±ΠΎΠ²Π°Π½ΠΈΠ΅ простой ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ β€” ΠΎΡ‡Π΅Π½ΡŒ Π²Π°ΠΆΠ½ΠΎΠ΅. Если Π²Ρ‹ Π·Π°Π΄Π΅Ρ€ΠΆΠΈΡ‚Π΅ ΠΏΠΎΡ‚ΠΎΠΊ своСй ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ, Ρ‚ΠΎ ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΡƒ Π·Π°Π΄Π°Ρ‡ придётся ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ Π½ΠΎΠ²Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ - what's the problem with that? Let him create. Doesn’t the parallel process create the same (new thread)? Or are you just talking about a web server? - tym32167
    • 1. Никакой синхронизации ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ². Никаких сСмафоров, мутСксов, ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΎΠ² ΠΈ ΠΏΡ€ΠΎΡ‡Π΅Π³ΠΎ 1. Никакой синхронизации ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ². Никаких сСмафоров, мутСксов, ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΎΠ² ΠΈ ΠΏΡ€ΠΎΡ‡Π΅Π³ΠΎ - this is also not understood, is there a dock about this? And how then to control access to resources? For example, I sometimes use asynchronous semaphore locking, what problems can there be with it? - tym32167
    • Well, here you are writing about I / O operations, but you can expect not only them. Are your recommendations just on waiting for input or output, or common to all cases? - tym32167
    • @ tym32167. You can read Richter in the book CLR via C # (there is a translation in Russian, look for the latest edition). You can read the Windows API documentation. You can start with docs.microsoft.com/ru-ru/windows/desktop/api/processthreadsapi/… - Mark Shevchenko