I will not respond on my own, but simply quote the words of .NET developers. After all, who else but they are the ultimate truth about how something should work.
Below is a very brief summary of the post "Should I expose asynchronous wrappers for synchronous methods?" from async / await developers and TAP creators. Know the language - read, do not know - translate by Google. But be sure to read.
Asynchrony
The two main advantages of asynchrony are scalability and unloading of the main thread (responsiveness of UI, concurrency). Different types of applications, as a rule, need different advantages: server applications need scalability, UI applications need unloading.
Scalability
The ability to run synchronous methods as asynchronous does not increase scalability, since the amount of resources spent remains the same — instead of the current thread, it runs in a different stream. Scalability of applications is achieved due to the fact that with the right asynchrony, the same resources do more work.
Unloading
In case of increasing responsiveness of UI and running code in parallel threads, wrapping the synchronous code in asynchronous is what you need.
Discussion
The .NET development team in Task-based Asynchronous Pattern does not recommend holding asynchronous methods in the API that simply wrap synchronous ones.
As already mentioned, in order to improve scalability, the code must be truly asynchronous — that is, source synchronous code needs to be redone. In the case of unloading - the original synchronous code does not need alterations. Moreover, if you provide only a synchronous version to the API, you get some bonuses:
- Less methods - less headache. Developers need less maintenance and testing. API users are less likely to suffer from the choice of which method to use in each particular case.
- According to the guideline, all methods contained in the API must be truly asynchronous. Those. Seeing the asynchronous method in the API, the user of the API needs to be sure that using it will improve scalability.
- The choice of whether to run the synchronous method asynchronously remains with the user. If he can "suffer" / allow circumstances - he will run the method synchronously. If he needs responsiveness, he will run the method asynchronously.
The main conclusion: the API should not lie and mislead .
From myself I can only say that as long as you write programs for yourself, or while you write code that no one else uses, these arguments may seem empty. But believe me, with serious development in the team, and even more so when creating libraries that are used by many developers, these rules turn out to be very useful.
It is also worth adding that the discussion above is about a public API . The degree of publicity may be different - it may be a library that is installed in hundreds with a nuge, or it may be your colleagues who use the component you have developed. It is only important that the public API is not misleading.
The statement "async over sync is bad" does not in any way apply to all code. Because, for example, if in the fully synchronous code they begin to use asynchronous methods, then it is clear that until the application is completely "penetrated" async/await , the code will contain "joints": asynchronous wrappers for synchronous methods. This is normal, this is a workflow. It is important to understand that async over sync should be either a forced measure (in the case of unloading) or a temporary measure (in the case of mixing), but not the norm .
The fact is that any thing (even a language feature, even a household appliance) should be made so that it would be easy to use correctly and difficult to use incorrectly. Unfortunately, the main advantage of async/await - easy asynchronous code writing - is at the same time its disadvantage. For example, because you can easily provide an asynchronous wrapper for synchronous code. This may lead to the fact that the developer can pair up with any synchronous method to provide an asynchronous wrapper. If we recall the previous patterns of asynchronous programming in .NET - Asynchronous Programming Model (methods BeginXXX / EndXXX ) and Event-based Asynchronous Pattern (method XXXAsync and event XXXCompleted ) - then it is much more difficult to make an asynchronous wrapper for the synchronous method. And the next thought after “And let me do the asynchronous version” will be the thought “Oh, well, who needs it, they will do it themselves”. Those. These models made you think carefully about whether an asynchronous wrapper is really needed. When using async/await this barrier is absent, so the developers have to actively talk and remind about this feature.
async/await:). - andreycha