I feel that c# has become a very wordy language and I'm not happy to have to code in the async style like this.
Oh, but that is not wordy at all. You are not writting something like this:
response => response.Content.ReadAsStringAsync().Then
And an API like the one above (probably a wrapper around
ContinueWith) it won't handle exceptions properly, you would probably need an
Error method with a callback to get the exceptions.
No, C# is not wordy.
Addendum: perhaps it is worth mentioning that if an
async method returns a
Task, it does not means you have to
await it. If you want the
Task to do something else with it (for example place it an array for
Task.WhenAll), you do not put the
await keyword. Therefore, the
await keyword is not redundant.
is creation of threads for async code going to impact performance?
No. Although some API do actually need to block on a
Thread – and I think that is the case for listening on a socket, at least on Windows – it will use the
ThreadPool, thus there won't be a lot of new
That it will use the
ThreadPool is not true for every API. Most will follow the following pattern:
The library creates a
The library sets a means to receive a notification. Callback, timer, message, whatever...
The library sets code to react to the notification that will call
SetException on the
TaskCompletionSource as appropriate for the notification received.
The library does the actual call to the external system.
The library returns
The call from step 4 goes to the external system. The external system responds, the response is received on the notification mechanism from step 2, then it sets the
Task completed, and afterwards the continuation of the
Task is scheduled (that continuation is what happens after your
How can I throttle the rate of calls if I'm calling GetAsync in a loop?
If you are awaiting it, then your code will not continue until it completes. Alternatively, if we are talking about having a limited number of
Tasks concurrently (not being awaited), I would suggest to use a
SemaphoreSlim. I would use it in conjunction with
Besides that, you probably will find
await Task.Delay(milliseconds) useful. It will use the pattern I described above, around a timer, no
Thread will be blocked waiting (unlike
has the c# team gone in the right direction creating this async paradigm in the language?
async/await is generally good. I agree that there is some overhead (creating
Task objects, et. al.). However, C# is doing better than most languages.
I understand the blue-red argument...
... on that, I would argue that if you want to follow the idea of a pure core and an impure shell, you will find that pure and impure and
async and "sync" are similar. The impure shell would deal with external systems. If you call an impure method from your method, your method is impure. Similarly, interacting with external systems is often
async, and if you want to
async method, you have to make your method
async propagating is annoying. The solutions is that the entry point will be impure (and
async) it will deal with external systems (impure imperative shell) and call into your not
async code (pure functional core), which returns to the shell for more interoperability. That way you do not have to make everything
async, and you do not have to make your whole code impure. If you are isolating external systems (for ease of exchanging them and ease of testing), you are probably doing this already.
I feel that go's approach of creating a thread by just saying go myfunction() is less long-winded, but I know it has it's performance penalties due to the green-threads used.
Is your complain that
await is longer to type than
go? that explains "wordy".
Asynchronous does not mean multi-threaded. For instance, we can read for the hard disk without having a
Thread waiting. You initialize the buffer where you will read, tell the operating system to tell the driver to tell the hard disk to write to that buffer (via DMA) and trigger an event. Then in the event we do
TaskCompletionSource.SetResult and then system can schedule the continuation (your code after
Thread, and you didn't have to worry about it. And yes, that is the same pattern I described above.
I find it hard to reason about what is happening behind the scenes of the compiler
The compiler is rewriting your code as continuations. It is a state machine. This is not the first time the compiler rewrites your code as a state machine, that would have been
co-routines iterators with
async method, each
await means that the code afterwards will be a continuation the
Task being awaited.
Please note that the
Thread calling will not be waiting. Instead, the async method schedules the first
Task, sets its continuation, and returns a
Task that will completed when all the continuations created for the method completes.
Actually, it is a bit more complicated because there is error handling, and it works with
try-catch-finally. The compiler does the rewriting.
That probably means that the calling
Thread will eventually be free to do work, if that is the case it could be used to run scheduled
Tasks. Sometimes the continuation will run on the same
Thread that called it, sometimes it will run on a different one. It is up to the
TaskScheduler. The default
TaskScheduler will use the
ThreadPool. And, yes, you can write a custom
Perhaps the interview Mads Torgersen: Inside C# Async can help you understand further. Strongly recommended.