async-await

Why Does ODP.NET Have Async Methods If They're Not Asynchronous?

The Oracle Client (ODP.NET) that we are using to build a major web project put us in a really stupid bind last week, ultimately causing me to waste two days in search of something that wasn't really going to work in the first place.

I'm on something of an async/await binge with this project, since in C# and ASP.NET it's really easy to implement and possibly gives you great scalability benefits. So, one of the first things I did was to make all our ORACLE accessing code asynchronous. There's a particular section of the code which needs to call a bunch of stored procedures in a row, and I figured that since the procedures don't really rely on each other, we'd benefit quite a bit by making them asynchronous.

All of this was going swimmingly, until this error started popping up:

"Connection must be open for this operation"

Not being a total expert on this, I would still expect that, given an asynchronous execution, each async call would have its own connection and so this error should never happen. And yet, there it was, repeatedly being logged into our exception logger.

So, to the Google I went, and eventually came across this StackOverflow post saying that the Oracle Managed Driver does not support asynchronous operations.

Yes it does! I thought. It's got all these async methods! They wouldn't name them "async" unless they were actually asynchronous! (Apparently I've never been on the internet before.)

In fact, the Oracle Data Provider for .NET does contain a few asynchronous methods:

  • ExecuteNonQueryAsync()
  • ExecuteReaderAsync()
  • ExecuteScalarAsync()

But the StackOverflow post says that these methods are not actually async, they are synchronous. So what's going on?

Browsing the features list for ODP.NET, I can't find any reference to asynchronous methods, the Task or Task<T> classes, or even the await keyword. In fact, I can't find any documentation at all that says these async methods need to exist, and yet they do. The question is: why?

Microsoft's own documentation says the following:

"In Visual Studio 2012 and the .NET Framework 4.5, any method that is attributed with the async keyword (Async in Visual Basic) is considered an asynchronous method..."

But it never actually specifies that the method has to actually be asynchronous! Rather, only that the method should return a Task or Task<T>, and even that is only a convention!

All the above is to say: technically, ORACLE did nothing wrong by suffixing these method names with "async", since in fact they do return a Task or a Task<T>. In fact, they might even be useful since they can be asynchronous with other, non-ORACLE-accessing methods. But that wasn't my scenario, and how was I supposed to know about this in advance?

The question becomes: since the methods themselves are not actually executed asynchronously, are they of any use?

Short answer? Nope. At least not for my situation. If anything, it's more harmful than helpful.

As far as I can tell, the only reason the asynchronous versions of these methods exist is to conform to some mythical interface mentioned in the comments of this StackOverflow answer. Which just begs the question: why does the interface need these method declarations? Ultimately I decided to get out of the rabbit hole before digging myself too deep and remove all my asynchronous code that used ODP.NET.

So now, in addition to the two days I spent researching this and implementing it for ORACLE calls, I now have to spend at least half a day removing it. All because ORACLE made some "asynchronous" methods that aren't actually asynchronous. Thanks ORACLE!

To anyone else out there who has to use ODP.NET: don't bother with the asynchronous methods unless you really know what you are doing. They're a lot more trouble than they are worth.

And, if you do really know what you are doing, tell me in the comments what situations these bloody things might actually be useful!

Happy Coding!

A Simple Explanation of Async and Await in ASP.NET

Once in a while, the technical presentations that I conduct at my day job force me to learn something new, something I'd never had to deal with before. This happened just last week, when my coworkers voted for the topic of the next session to be Async and Await in .NET. These two keywords make writing asynchronous code much simpler than it was before .NET 4.5.

I'll be perfectly honest: until last week I know nothing about asynchronous programming. Nada. Zip. Zilch. But after doing some research and creating my own sample project, I'm starting to see why Stephen Cleary said that "Async will fundamentally change the way most code is written".

In the spirit of not caring that I suck as long as I'm learning I decided to just dive right into learning about async, await, and asynchronous programming in general. I had one problem though: I found precious few resources that were able to explain to me the concepts of asynchronous programming in simple terms.

I seek to remedy that with this post.

I'm not going to go into great detail about the ins and outs of asynchronous programming in .NET; rather, I'm be focusing on taking these opaque concepts and breaking them down into simple, understandable examples. This helped me better understand exactly what I'm doing when I use these keywords, and hopefully it'll help you too. Let's get started!

What is Asynchronous Programming?

Asynchronous programming is writing code that allows several things to happen at the same time without "blocking", or waiting for other things to complete. This is different from synchronous programming, in which everything happens in the order it is written (if you write code for a living, chances are it will be synchronous code).

Let's look at a synchronous C# method:

public string GetNameAndContent()  
{
    var name = GetLongRunningName(); //Calls another webservice, can take up to 1 minute.
    var content = GetContent();  //Takes up to 30 seconds
    return name + ": " + content;
}

Every time something calls this method, the caller has to wait up to 1 minute before it can resume processing. That's a minute of wasted time, time it could be spending doing other tasks.

With .NET asynchronous programming, we can modify this method like so:

public async Task<string> GetNameAndContent()  
{
    var nameTask = GetLongRunningName(); //This method is asynchronous
    var content = GetContent(); //This method is synchronous
    var name = await nameTask;
    return name + ": " + content;
}

We made three changes to the method:

  1. We marked the method as async. This tells the compiler that this method can run asynchronously.
  2. We used the await keyword on the nameTask variable. This tells the compiler that we will ultimately need the result of the GetLongRunningName() method, but we don't need to block on that call.
  3. We changed the return type to Task<string>. This informs the caller method that the return type will eventually be string, but not right away and that can do other things while GetLongRunningName() is processing.

But even this wasn't obvious to me. What were we actually doing when "waiting" for GetLongRunningName() to finish?

This is the difficult part to put in simple terms, but I'll try anyway. Essentially, the system wants to execute GetLongRunningName() because it was called first, but because it is an async task and we are awaiting it, control is relinquished to fire GetContent(), which means we now have the work for two methods running at the same time. What this does not do is spin up another thread; using async and await do not cause threads to be created.

(If you want a more in-depth explanation of what happens during an async invocation, MSDN has you covered. It's the best example I could find, complete with a diagram.)

Waiting on Multiple Calls

Let's see another example. Say I have a class called ContentManagement, which has both synchronous and asynchronous methods:

public class ContentManagement  
{
    public string GetContent()
    {
        Thread.Sleep(2000);
        return "content";
    }

    public int GetCount()
    {
        Thread.Sleep(5000);
        return 4;
    }

    public string GetName()
    {
        Thread.Sleep(3000);
        return "Matthew";
    }
    public async Task<string> GetContentAsync()
    {
        await Task.Delay(2000);
        return "content";
    }

    public async Task<int> GetCountAsync()
    {
        await Task.Delay(5000);
        return 4;
    }

    public async Task<string> GetNameAsync()
    {
        await Task.Delay(3000);
        return "Matthew";
    }
}

ContentManagement is just a simple demo class that imitates having some long running calls. Note that three of the methods are marked async, and (by convention) the word Async is appended to the method name. We'll explain why we need both synchronous and asynchronous methods in the Potential Issues section below.

Now let's write an MVC controller, like so:

public class HomeController : Controller  
{
    [HttpGet]
    public ActionResult Index()
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();
        ContentManagement service = new ContentManagement();
        var content = service.GetContent();
        var count = service.GetCount();
        var name = service.GetName();

        watch.Stop();
        ViewBag.WatchMilliseconds = watch.ElapsedMilliseconds;
        return View();
    }

    [HttpGet]
    public async Task<ActionResult> IndexAsync()
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();
        ContentManagement service = new ContentManagement();
        var contentTask = service.GetContentAsync();
        var countTask = service.GetCountAsync();
        var nameTask = service.GetNameAsync();

        var content = await contentTask;
        var count = await countTask;
        var name = await nameTask;
        watch.Stop();
        ViewBag.WatchMilliseconds = watch.ElapsedMilliseconds;
        return View("Index");
    }
}

(As an aside, the Stopwatch class is super useful when trying to record time of execution.)

Notice what these two actions are doing. In both cases, the actions are calling the methods in the ContentManagement service, but in one they are doing it asynchronously.

On our Index view, we have an output which displays the WatchMilliseconds value. Let's see what the Index action renders:

A snippet of the Index view, showing that 10002 milliseconds elapsed.

Intuitively, this makes sense. We called three methods; they took 2 seconds, 5 seconds, and 3 seconds respectively to execute; so the total execution time should be around 2 + 5 + 3 = 10 seconds.

Now watch what happens if we call the IndexAsync action:

A snippet of the IndexAsync action's view, showing that the method took 5007 milliseconds to execute.

Where did we get that number? The longest-running of the three tasks takes 5 seconds. By designing this to use async, we cut our total execution time in half! That's a lot of speedup to be gained from writing a little extra code!

Return Types

OK, great, so why we'd want to do this makes sense now, at least to me. But what exactly is that Task<ActionResult> thing we'd used in the IndexAsync action?

There are three return types we can use when writing an async method:

  • Task: This class represents an asynchronous operation, and can be awaited.
  • Task<T>: This class represents an asynchronous operation that returns a value, and can be awaited.
  • void: If an async method returns void, it cannot be awaited. This essentially turns the method into a "fire and forget" method, which is rarely the desired behavior. Further, the error handling on async methods that return void is quite a bit different, as shown by Stephen Cleary. There's no good reason to use void as a return type from an async call unless you do not care at all whether that call actually finishes.

In short, almost every asynchronous method will use Task or Task<T> as their return type. The Task class represents the asynchronous action itself, not the result of that action. Calling await on the Task means that we want to wait for the Task to complete, and in the case of Task<T>, want to retrieve the value that the Task returns.

Potential Issues

Let's be clear about something: most apps will probably not see such dramatic improvements (50% speedup!) from implementing asynchronous programming. Again, we're not going to be turbo-charging individual methods, just executing them at the same time. In fact, if we design our asynchronous methods incorrectly, we can actually hurt overall performance.

When we mark a method as async, the compiler generates a state machine in the background; this is extra code. If we write good, stable asynchronous code, the amount of time it takes to create this extra structure won't impact us at all, since the benefits of running asynchronously outweigh the cost of building the state machine. However, if our async method doesn't have an await, the method will run synchronously, and we will have spent extra time creating the state machine that we didn't use.

There's one other potential problem to be aware of. We cannot call an asynchronous method from a synchronous one. Because async and await should go together in all cases, we pretty much have to have async on all methods, all the way down. This is why we needed separate async methods in the ContentManagement class earlier. Ultimately, this results in having more code, which means more things that can theoretically break. However, given a good design and solid understanding of what we are trying to accomplish, having that extra code also leads to greater performance, so in my mind it is a fair trade-off.

Summary

A little extra effort in implementing asynchronous goes a long way to improving performance and responsiveness of our apps. .NET has made it easy to do with the async and await keywords, and now we can implement asynchronous design simply, concisely, and quickly.

I went into this exercise knowing precisely nothing about asynchronous programming; now I can at least say I know more than nothing. Hopefully, you can too (and if you can, let me know in the comments!)

If you need more information, take a look at Async in C# 5.0 by Alex Davies, which I've read and helped immensely when trying to understand what async/await does in an MVC web application.

I built a sample project using Visual Studio 2015 and ASP.NET MVC (including the ContentManagement class and HomeController we used earlier), and it's on GitHub, so go check it out!

Happy Coding!