4

We have an asp.net application, it makes no use of async or parallel methods(except for some owin middleware).

I want to start using the async version of some methods using the async-await syntax.

I know that there is danger in mixing async and sync operations as that might cause a deadlocks.

It is not possible to rewrite the whole app in one go.

Where should I Start? is the safe way to do it to make the controllers actions async and work my way down? or the other way around?

Is there some clear warning sign(s) that I can watch for along the way like: "never have a sync method call an async method, but it's fine to have async call sync"

user1852503
  • 4,747
  • 2
  • 20
  • 28
  • 1
    Just want to make sure that you are aware that async only helps in special situations on the server: http://stackoverflow.com/a/25087273/122718 Most of the time it will have negative benefit. – usr Feb 18 '15 at 10:49
  • Unless you have good performance tests, what you're doing counts as premature optimization. You must have tests to show you what your performance problems are (and what they are not). When you run these tests as you are moving towards async, they will also catch the cases where `async` makes things worse. – John Saunders Feb 18 '15 at 21:43

3 Answers3

3

Where should I Start? is the safe way to do it to make the controllers actions async and work my way down? or the other way around?

I recommend starting at the "leaves" and creating "vertical partitions". That is, within a service or data access layer, identify I/O-bound operations. Then create asynchronous copies of those methods that use naturally-asynchronous APIs. Once you have those, then continue "up" your layers, creating asynchronous copies, until you can make a controller action asynchronous.

You'll end up with a fair amount of code duplication - both synchronous and asynchronous versions of the same method - but this is only temporary. Once all the other code only uses the asynchronous version of a method, the synchronous version can be removed.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
2

You can safely mix sync and async IO. The deadlock arises from the way await automatically uses the ambient SynchronizationContext. Platform methods such as Stream.Read almost never do this.

Start with making long-running IO async. Short-running IO is more likely not to benefit.

usr
  • 168,620
  • 35
  • 240
  • 369
2

It's completely safe to mix async and sync operations in your code. What's dangerous is using "sync over async" when you block on asynchronous operations inside synchronous ones.

As long as when you change a single operation you make sure it's async all the way you can add more async operations gradually.

i3arnon
  • 113,022
  • 33
  • 324
  • 344
  • please explain "sync over async" more. perhaps with an example of what not to do. are you saying that a single controller action must be async but cna live along side others taht are not? similar to the answer Cleary gave? – user1852503 Feb 18 '15 at 20:12
  • @user1852503 "sync over async" is blocking on an `async` operation. That means `FooAsync().Result` or `FooAsync.Wait()`. The `async` way is to use `await`: `await FooAsync()`. That means that the calling method needs to be `async` too which should be awaited and so on and so on. That's "async all the way". See more [here](http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx) – i3arnon Feb 18 '15 at 20:24
  • @user1852503 So peek an IO operation, lets say `Read()`, use the `async` version instead `await ReadAsync()`, mark the method as `async` and `await` it in the calling method etc. etc.. Then change another operation and another until you're done. – i3arnon Feb 18 '15 at 20:27