5

After exposing to Windows App Store development for a month, I begin to feel that async / await programming model does more harm than good. It makes simple thing complicated.

Take an example, folder creation. In Java or Desktop .NET, I can simply do

Java

public Constructor()
{
    new File("c:\\folder").mkdirs();
    System.out.println("I am pretty sure c:\\folder is ready now");
}

Desktop .NET

Constructor()
{
    System.IO.Directory.CreateDirectory("c:\\folder");
    Console.WriteLine("I am pretty sure c:\\folder is ready now");
}

But when comes to

Windows App Store .NET

Constructor()
{
    // Damm it! Another async function? I don't need aysnc!
    Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync("c:\\folder", CreationCollisionOption.OpenIfExists);
    // I am not sure c:\\folder is ready right now!
    // OK. I know I can use ContinueWith. No no no. I don't want.
    // Why I have to use ContinueWith with such a simple operation?
}

So, my question is, do you find the newly introduced async / await programming model in Windows App Store,

  • Improve your productivity?
  • Make programming life easier?

For me, I don't! Perhaps I have been missing out certain useful techniques.

I know, Microsoft says, it helps us to write responsive UI code.

But I would say, No thanks! Hey look, my code is already in non-UI code!

Most of my current operation code is fast enough and doesn't block UI. When my operation code is not fast enough, I am pretty comfortable in making those slow operation code run in separate Thread/ Task.

Forcing me to use async / await which I do not need, only makes my code more complicated.

Message to Microsoft : May I beg to you, besides async functions, can you provide a same set of non-async functions, please? I already build up my habit of running code in non-UI thread. I promise I will continue make your Windows App perform as smooth as iOS :)

20
  • 4
    It allows you to write responsive UI code without having to move all I/O operations to a separate thread. Commented Nov 28, 2012 at 15:22
  • 1
    I'm not super familiar with windows 8, but any sort of restriction on creating directories comes from that API. Nobody's forcing you to use async for everything, all of the synchronous methods are still there.
    – Telastyn
    Commented Nov 28, 2012 at 15:22
  • 6
    How much async code have you written? It is complicated and difficult to get right. async and await make it much easier by making the compiler do the hard work. The Java and "Desktop .NET" examples you gave are synchronous, not asynchronous. Rewrite them as asynchronous functions in both languages, without async and await, then come back to this question.
    – Oded
    Commented Nov 28, 2012 at 15:25
  • 1
    You're using the wrong comparison. You're comparing the old synchronous operations with new asynchronous operations, to make clear what you're replacing you should compare the old asynchronous operations with the new asynchronous operations, and you will then see that the new technique is simpler. Also the new approach is naturally faster due to the plumbing of when it actually becomes a separate thread Commented Nov 28, 2012 at 15:52
  • 4
    You are not using the await/async keywords at all in your example! Commented Nov 28, 2012 at 16:25

7 Answers 7

10

You're probably holding it wrong (just some context for the statement).

Unfortunately I haven't had a chance to play with Win8 yet, but based on code examples I've seen, your code should look more like

Constructor()
{
    // Damm it! Another async function? I don't need aysnc!
    var result = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync("c:\\folder", CreationCollisionOption.OpenIfExists);
    // by the time your code gets to this line, the folder will have been created
}

The other option (if you can't make your method async) is to block the thread until async opertation completes by calling GetResults. Probably something along the lines of

Constructor()
{
    // Damm it! Another async function? I don't need aysnc!
    var result = Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync("c:\\folder", CreationCollisionOption.OpenIfExists);
    result.GetResults();
    result.Close(); // According to documentation, you should call this when done
    // Voila, 
}

Though it looks like you're doing file IO inside a constructor and you probably can't have async constructors, so the first option is out. I assume this this is just some contrived example and not representative of your code, but my feeling is if you find yourself doing IO inside a constructor and you're not writing a framework class (like FileInfo), you should take a second look at your design. I generally don't expect newing up a class to start creating/locking system resources.

There are a couple of related questions on StackOverflow regarding constructors and async

2
  • 2
    Oh, you can't use await in constructor. and believe me, if you use GetResults, it will crash with System.InvalidOperationException :) Try it and you will know. I believe after some tries, you will have the same feeling as I'm Commented Nov 28, 2012 at 16:27
  • I added some links regarding async and constructors.
    – Roman
    Commented Nov 28, 2012 at 17:31
13

The problem here isn't the async/await keywords but the fact that many WinRT APIs are only offered in an async form. In the past, APIs have been offered in a blocking form, or your choice of blocking and non-blocking, and developers were supposed to make sure the UI didn't hang. Well guess what? Developers didn't bother. I've waited multiple minutes for a Print dialog in an Office product to finish timing out on contacting whatever printer I used last time, before I could specify that I don't want that printer, usually because that printer is now thousands of miles from me. The vast majority of applications were written the easy way for the developer even though that might create a bad experience for the user.

So the new API has no blocking form. You have to learn how to do it asynchronously, like it or not. You could set up a completed handler and then start the process, or you could use the new C# keywords. Your choice. But developers will no longer be trusted to keep the promise you offer to make. And rightly so, since almost no-one did.

6
  • We lost freedom to choose then :( You know, programmers love freedom. Commented Nov 28, 2012 at 16:28
  • 4
    You can look at it that way. Or that now you no longer have to learn two ways plus how to choose between them. That had its problems too, didn't it? Commented Nov 28, 2012 at 16:34
  • Right. Too much choices is a new set of problem :) Freedom always comes with price. Even though, I still prefer freedom more. democratic vs dictator? Commented Nov 28, 2012 at 16:37
  • 2
    From Microsoft's perspective, it is their product that would be eventually blamed --the developer will probably be too but they clearly have more at stake.
    – Apoorv
    Commented Nov 28, 2012 at 16:45
  • 5
    @YanChengCHEOK Is losing the freedom to choose the wrong option really so terrible? Strict functional languages are highly restrictive compared to, say, C++ - and yet people who understand them are in love, in part because the restrictions mean that it's significantly harder to make incorrect choices. Eric Lippert talks about this philosophy in his post on the Pit of Despair vs the Pit of Quality.
    – Tacroy
    Commented Nov 28, 2012 at 17:00
5

I think, in something of a departure for Microsoft, they have thought about what makes for the best user experience rather than what makes for the easiest developer experience.

Certainly adopting the async model requires more work on the part of the developer, but just maybe gives that developer a better chance of producing something that will be responsive to the user.

You only need to use Outlook to see how bad the user experience can be if you follow a synchronous programming model too much.

2
  • 2
    +1 for the outlook comment, just previewing a mail could freeze the entire program Commented Nov 28, 2012 at 16:42
  • @Martin - An Async model is easier on the developers if thats their only choice.
    – Ramhound
    Commented Nov 28, 2012 at 17:55
2

await was introduced with .NET v4.5 and is actually a way to break the pure asynchronous approach. So it's there as a way to simplify coding with asynchronous methods / calls.

It can also be abused if you put await on every single one of your calls. At that point, you're back to "traditional" coding styles where you have to wait for all actions to return.

Asynch is a useful approach when you're making calls across a network or when other actions can continue while awaiting the results of the call. It's equivalent to using a background thread to handle some form of data processing. The rest of the app continues along until the task is done.

As you noted in your example, there are some cases where you simply have to wait until a call completes before operations can continue. That's where the await keyword comes in handy. An alternative was to have a callback method that the performed the rest of the processing. Honestly, that alternative is less than elegant, and I'm glad that await was offered up.

So, just like with any other tool:

  • Use asynchronous methods as appropriate for the calls your app is making.
  • Use the await keyword judiciously when there are calls that really must block the rest of the operations. Don't overuse the keyword as that will hamper your application.
3
  • You're absolutely right, but I think the OP might be referring to the fact that so many "Windows Store App" APIs are offered only in an async form. Sure for your own functionality you have a choice, but when calling their API you don't. I could be wrong though :-)
    – Martin
    Commented Nov 28, 2012 at 15:51
  • 1
    @Martin - I read the Windows Store aspect as unnecessary obfuscation of the core question. MS has moved to requiring an async model with most of their newer development frameworks. WCF, ASP.NET MVC v.whatever, Win8 RT, etc... require an async approach. Since he's writing to Win8 RT | metro, he doesn't really have a choice to use async or not. But it's not a "Windows Store" issue, per se.
    – user53019
    Commented Nov 28, 2012 at 15:57
  • 1
    Await does't block the thread, so what you are saying isn't strictly true. If you for instance await in the painting thread, no real harm is done. Blocking there would OTOH be really bad. Commented Nov 20, 2015 at 18:34
2

Actually, Async/Await makes an unnecessarily complicated thing much simpler. (Just imagine if you had to do all that without Async/Await!) The unnecessarily complicated part is Microsoft's decision to make all those APIs async-only, instead of leaving it up to the discretion of the developers.

1
  • 2
    Did Microsoft have a choice? Based on the quality of a small but huge number of iOS applications and pretty much every Android application being so poor, and lets face it 99.9% of Windows applications have some sort of hack in them, means they had to make it required for developers to do things the proper way. I don't think the users will complain.
    – Ramhound
    Commented Nov 28, 2012 at 18:01
2

I see that the problem here is that you can't use await in a constructor and that GetResult won't work. But have you tought about using a static helper method to create your object?

class AsyncCreated
{
    public static async Task<AsyncCreated> CreateWithFolder()
    {
        var folder = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync("c:\\folder", CreationCollisionOption.OpenIfExists);

        return new AsyncCreated(folder); // There you do the usual stuff
    }

}

// elsewhere in your code

var myObject = await AsyncCreated.CreateWithFolder();

The added bonus is that now it's more explicit that some work is being done while you initialise the type.

1
  • 1
    In my opinion, this is one of the better more thoughtful answers to the question. This is exactly what the OP needs - an alternative approach that illustrates how the task can be accomplished while still benefiting from the asynchronous nature of await/async calls.
    – Carlos P
    Commented Dec 19, 2013 at 14:40
1

It might.

But what's probably really happening is that it is keeping complicated things complicated.

Creating a file is complicated. It can be over a network share. It can already exist. The hard drive might be slow. It might be a RAM disk. Point is, it can take different amounts of time, or might outright fail.

Jeff Atwood wrote a great post about this 8 years ago. He basically said that we should embrace multithreading and asyncronous code, but most developers aren't prepared to deal with it because it's a very complex topic, and the tools at the time weren't suitable to make it easy enough to write asynchronous code.

The async and await keywords (along with other tools, like the thread-safe collections) are Microsoft's answer to his request to improve the tools to bring easy async programming to the unwashed masses. My opinion is that they have mostly succeeded. In that a majority of cases, you can use the async APIs in WinRT as if they were not asynchronous, then just pepper in a few async and await keywords, compile and bask in the glow of responsive, non-blocking code.

Constructors, as well as a few more things, are where the limitations of the tools appear and trip up even the average programmer, who is just trying to write a program to do his job.

Jeff also commented that one reason why BeOS failed to attract developers was because, like WinRT, the entire OS API was asyncronous, and writing anything beyond a utility was torture. I think for the most part it's a small learning curve, but the tools are much more approachable than they were 8 years ago. We'll see how Microsoft fares in the future.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.