Await (keyword)
This is a Language topic about Oxygene
Language Topics Introduction | Structured Overview | Grammar | Keywords | Functions
(This page is is a work in progress and not considered finished yet)
(TODO: this page is considered to be complete, but is pending final verification for full accuracy)
The Await Keyword is a new Oxygene language feature introduced in Oxygene 5.1. It's an expression type that allows you to use the result of an asynchronous call in a synchronous way. While the code looks synchronous, it actually runs asynchronously, so it doesn't block the thread it is running on. This greatly reduces the complexity of asynchronous code while improving the responsiveness of apps.
Simply put, “await” lets you use the result of an asynchronous operation (such as the result of many of Metro’s and .NET 4.5 new APIs) or — only in Oxygene — an async future, and have the resulting code be “wrapped around” to run asynchronously, as well.
In Oxygene, when you access a async future‘s value, your code will block right there, and wait for the future to complete before it continues executing — after all you’re using the value, and that value has to come from somewhere.
Using the “await” keyword, your code will look and work much the same as without, except your code will not block. Instead, all parts of the code that depend on the future value (or otherwise precede your accessing it) will be extracted and moved into a separate block of code that runs asynchronously.
This is best seen with a concrete example, so consider the following code:
method MainForm.CountFiles(aStartFolder: String): Int32; begin result := Directory.GetFiles(aStartFolder).Length; for each d in Directory.GetDirectories(aStartFolder) do result := result+CountFiles(d); end; method MainForm.button1_Click(sender: System.Object; e: System.EventArgs); begin var x := async CountFiles('C:\'); MessageBox.Show('You have '+(await x)+' files.'); end;
Without the use of "await" (or without the use of the "async" keyword, which turns "x" into an *async future Int32*), this button click event would block, and your entire application would be hung while the program crawls across your harddisk to count files.
The async future, on its own, has the potential of making the the count asynchronous, but the following "MessageBox.Show" would block right away, making the use of the *future* essentially useless. Complex code could be written to wait for the future and then trigger the message box from a different place in code.
But "await" takes care of all that; it allows you to write code using the "naïve" approach without worrying about application flow. You can concentrate on your application logic, and the complexities of threading (and synchronization of results back to the main thread) are handled for you.
So what happens when you run this? Easy: when you click the button, our *async future* is created and started, causing the (recursive) call to CountFiles. Once that is up and running, the event handler is done and returns control to your application. Now the future is running in the background, counting files, and probably taking a few minutes to do it, depending on your harddisk size.
Once the future is complete, the message string is assembled and "MessageBox.Show" is called to display it — also on the main thread, synchronized via the application's message loop.
All this time, your application remains responsive! As a matter of fact, in the example above, i could go ahead and click the button several times, launching a handful of independent file scans (which of course makes little sense in this scenario — a real app could disable the one button, or might let you scan different folders at the same time, getting the path from an edit field) that run in parallel, and will each eventually respond with a message box, one by one.