问题描述:

This question already has an answer here:

  • Using async await when implementing a library with both synchronous and asynchronous API for the same functionality

    1 answer

网友答案:

You want to add async methods in addition to the synchronous ones in your lib. The article you linked to talks exactly about that. It recommend to create specialized code for both versions.

Now that advice is usually given because:

  1. Async methods should be low-latency. For efficiency they should use async IO internally.
  2. Sync methods should use sync IO internally for efficiency reasons.

If you create wrappers you might mislead callers.

Now, it is a valid strategy to create wrappers both ways if you are OK with the consequences. It certainly saves a lot of code. But you will have to decide whether to give preference to the sync or to the async version. The other one will be less efficient and have no performance-based reason to exist.

You will rarely find this in the BCL because the quality of implementation is high. But for example ADO.NET 4.5's SqlConnection class uses sync-over-async. The cost of doing a SQL call is far greater than the sync overhead. That's an OK use case. MemoryStream uses (kind of) async-over-sync because it is inherently CPU-only work but it must implement Stream.

What's the overhead actually? Expect to be able to run >100 million Task.FromResult per second and millions of almost zero work Task.Run per second. That's small overhead compared to many things.

网友答案:

Would it then be ok to have a wrapper of the synchronous to be just Task.Result or Wait()?

You have to understand what async IO is all about. Its not about code duplication, its about taking advantage of the fact that you don't need any threads when the work is naturally asynchronous.

If you'd wrap your synchronous code with a task, you're missing out on that advantage. Also, you'd be misleading your API callers when they'd assume the awaited call would yield control back to the caller.

Edit:

Your examples strengthens my point. Don't from the use of tasks. Synchronous apis by themselves are completely fine, dont force the use of TPL into them when it isn't needed, eveb if it causes your codebase to grow 2x the amount of lines.

Take the time to implement your async api correctly. Don't block on async code, keep it flowing all the way to the bottom of the stack.

相关阅读:
Top