async vs non-async methods in a new library [close

2019-06-17 03:39发布

In .NET 4.5, there are many methods that now come in async and non-async pairs, such as Flush() and FlushAsync(). Ideally I/O interactions would always be asynchronous where possible (you can always block with .Wait() if you really want to), but the non-async (blocking) versions obviously need to remain due to backwards compatibility.

When rolling out a completely new library that has no backwards compatibility restrictions, is there any reason why one would include the non-async methods?

4条回答
Viruses.
2楼-- · 2019-06-17 04:23

There are slight differences (mostly negligible) between async and synchronous versions but I would say that there's no reason anymore to have both versions of the same operation. You should decide during the implementation of your library which version fits best. A naturally asynchronous operation (e.g. downloading a file) should be async and CPU bound operations should be synchronous.

You can see that paradigm being used in the WinRT framework:

To achieve those goals, we made many potentially I/O-bound APIs asynchronous in the Windows Runtime. These are the most likely candidates to visibly degrade performance if written synchronously (e.g. could likely take longer than 50 milliseconds to execute). This asynchronous approach to APIs sets you up to write code that is fast and fluid by default and promotes the importance of app responsiveness in Metro style app development.

From Keeping apps fast and fluid with asynchrony in the Windows Runtime

It used to be the case that using the asynchronous overloads was immensely harder and more complicated than the synchronous ones so having both versions was a good idea. With async-await that is no longer the case.

查看更多
走好不送
3楼-- · 2019-06-17 04:25

The only reason is if you want support applications that targets a .NET Framework prior 4.5. If you have such applications and you want to use your new library then you are forced to use the non async way.

You can compile your new assembly also with .NET 4.0 by using the Async Targeting Package.. Doing that I suggest you to create two projects: one with 4.5 and one with 4.0.

查看更多
祖国的老花朵
4楼-- · 2019-06-17 04:37

Async methods usually have a cost associated with them as there is a state machine generated by the compiler which results in quite a bit of extra code. If you are not using the async methods they won't be jitted so you avoid that cost.

If you use the async version and simply call Wait() you are risking a deadlock and also you would incur an extra context switch once the async operation completes. So overall the result would perform slightly worse.

Also any exceptions you get will now be wrapped in an AggregatedException so there will be extra work in exception processing as well. Have a look at Async Performance: Understanding the Costs of Async and Await

查看更多
Animai°情兽
5楼-- · 2019-06-17 04:44

Ned's answer is pretty good, so I will not repeat what he said (although do note that the overhead isn't necessarily large compared to the cost of the I/O operation itself).

One more significant reason to provide the synchronous methods is actually obvious in hindsight - people have serious trouble understanding asynchronous operations. They're used to doing "Read, then write, then read again..." Error handling, error locality, synchronization... all can get very tricky very easily, especially if you can't use await.

The truth is, while it would be very nice if everything became asynchronous over time, it's much harder to reason about asynchronous applications. It's still better than doing multi-threading, but not by a whole lot.

In this way, using asynchronous methods can be seen as an optimization - and you don't do optimizations unless you know they're going to help significantly. For a library, this is tough to decide - so provide both options. Someone writing a high-throughput server will take the care needed to write a performant and reliable asynchronous application. Someone just writing a simple CMS, for example, might want to avoid it entirely.

This applies especially for C#/.NET below 4.5 - try doing error handling on asynchronous continuations without await, and you'll see what I'm talking about :)

Keeping code simple is very important. It lowers development and maintenance costs considerably, and makes it easier to understand for newcomers.

查看更多
登录 后发表回答