Greater Productivity with Visual Studio 2012
August 7, 2014IP-Based Licensing Makes Its Debut
August 7, 2014Improve the responsiveness of your application without increasing the complexity of your code in Synergy/DE 10.1
Sometimes with large applications, we have sections of code that are not as responsive as we’d like them to be, such as code that retrieves information from the web. As a result, an application can appear to hang, and so we resort to adding a graphic, such as progress bar, to indicate that work is actually being done. This is a nice way to prevent the user from aborting, but what if the application could make the web request and continue on with other work, going back to get the results only after the retrieval was complete?
That’s the goal of asynchronous programming. Traditional techniques for doing this type of programming can be painful, in that they require a lot of development work to maintain the state of the request within the application. In Synergy .NET version 10.1, however, we’ve greatly simplified asynchronous programming by adding support for two new keywords: ASYNC and AWAIT.
Adding an ASYNC modifier to a method indicates that it is an asynchronous method, which is a non-blocking operation. Within an asynchronous method, we can then use the AWAIT statement on asynchronous tasks that need to be waited for within the method. These AWAIT statements denote suspension points within the ASYNC method; if the task is not done, the method is exited immediately so other application work can continue. When the awaited task is complete, the application returns to that spot and continues the application logic within the ASYNC method until it either reaches another AWAIT suspension point or the method completes.
Using ASYNC requires .NET Framework 4.5. The return type for the ASYNC method must be Task or Task<T> (which are .NET Framework classes that contain information to indicate when a task is complete) or void. Also, the expression following AWAIT must give a Task-based result.
In the code below, the clickit() method is marked ASYNC and has three awaited tasks that get the titles of unique web pages. This program can be compiled using Synergy .NET 10.1 with the following command line:
dblnet -ref=System.Windows.Forms.dll,System.Drawing.dll <myprogram.dbl>
import System
import System.Windows.Forms
import System.Net
import System.Text.RegularExpressions
namespace WindowsFormsApplication1
class Form1 extends Form
public method Form1
proc
InitializeComponent()
end
private method InitializeComponent, void
proc
this.listBox1 = new System.Windows.Forms.ListBox()
this.button1 = new System.Windows.Forms.Button()
this.SuspendLayout()
this.listBox1.FormattingEnabled = true
this.listBox1.Location = new System.Drawing.Point(51, 82)
this.listBox1.Name = "listBox1"
this.listBox1.Size = new System.Drawing.Size(200, 147)
this.listBox1.TabIndex = 0
this.button1.Location = new System.Drawing.Point(100, 26)
this.button1.Name = "button1"
this.button1.Size = new System.Drawing.Size(75, 23)
this.button1.TabIndex = 1
this.button1.Text = "Get Titles"
this.button1.UseVisualStyleBackColor = true
this.button1.Click += new System.EventHandler(this.button1_Click)
this.Controls.Add(this.button1)
this.Controls.Add(this.listBox1)
this.Name = "Form1"
this.Text = "URI Titles"
this.ResumeLayout(false)
end
private listBox1, @System.Windows.Forms.ListBox
private button1, @System.Windows.Forms.Button
private method button1_Click, void
sender, @*
e, @EventArgs
proc
listBox1.Items.Add("work before")
clickit()
listBox1.Items.Add("work after")
end
public async method clickit, void
proc
data wc1, @WebClient, new WebClient()
WriteLinePageTitle(await wc1.DownloadStringTaskAsync(new Uri("http://www.weather.gov")))
WriteLinePageTitle(await wc1.DownloadStringTaskAsync(new Uri("https://www.synergex.com")))
WriteLinePageTitle(await wc1.DownloadStringTaskAsync(new Uri("http://www.microsoft.com")))
end
public method WriteLinePageTitle, void
page, string
proc
listBox1.Items.Add(GetPageTitle(page))
end
public method GetPageTitle, string
page, string
proc
data titleRegex, @Regex, new Regex("\<title\>(?<title>.*)\<\/title\>", RegexOptions.IgnoreCase)
data match = titleRegex.Match(page)
if (match.Success) then
begin
mreturn "Page title: " + match.Groups["title"].Value
end
else
begin
mreturn "Page has no title"
end
end
endclass
endnamespace
main
proc
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(false)
Application.Run(new Form1())
end
When running this program, clicking on the “Get Titles” button causes button1_click() to execute. This causes “work before” to be output, followed by a call to clickit(). Because clickit() is designated ASYNC, the routine executes all the way up to the first AWAIT statement. Since the task for that first AWAIT is not complete, clickit() is exited, and execution within button1_click() continues, causing “work after” to be displayed. Once the first AWAIT statement in clickit() is complete, the execution of clickit() displays the first page title. Then execution continues up to the next AWAIT statement. After the second task is complete, the second title is displayed, and execution continues up to the next AWAIT. After the third AWAIT task is complete, the third title is displayed. To accomplish all of this, the compiler generates a lot of code to maintain state — code that you would have had to write manually before the introduction of these two very helpful keywords.
In short, AWAIT and ASYNC can be used to improve the responsiveness of your application without increasing the complexity of your code. If you would like more background on asynchronous programming, check out this article on Microsoft’s web site.
For more information about the ASYNC qualifier and the AWAIT statement, see METHOD and AWAIT in the Synergy/DE documentation.