Micro Focus COBOL under .NET (and JVM)
For the last twenty years Micro Focus has invested to COBOL running under .NET to match the equivalent capabilities with other languages that run in that environment (often called "managed code") such as Java, C#, and VB.NET, in terms of features and constructs.
Today Micro Focus Visual COBOL (and its mainframe-application sibling Enterprise Developer) can compile COBOL code directly to JVM bytecode and to CIL (for .NET framework and .NET core). Interacting with other JVM or .NET libraries has never been easier thanks to new managed syntax that can be used directly in COBOL programs.
In this blog I will demonstrate writing asynchronous code using the new async
/ await
syntax for COBOL running under .NET (hereafter called .NET COBOL) which is available in the latest release of Visual COBOL and Enterprise Developer.
Synchronous
Synchronous code is where each line of a program is executed one at a time. The next line is only executed when the previous line has completed no matter how long that might be. For example if a program first needed to download a file and then read it, it would only read that file as soon as the download had completed.
Let's take a look at the following snippet of code.
method-id GetEmployeeDetails (id as binary-long)
returning employee as type EmployeeDetails.
declare account = GetUserAccount()
set employee to QueryEmployee(id)
if not account::HasAccessRights(employee)
raise new AccessDeniedException()
end-if
end method.
method-id btnGetEmployee_Click (sender as object, e as type EventArgs).
try
declare employee = await GetEmployeeDetails(binary-long::Parse(txtId::Text))
invoke ShowEmployeeDetails(employee)
catch ex as type Exception
set lblStatus::Text to ex::Message
end-try
end method.
Notice how GetEmployeeDetails
must first fetch the user account and then after that has completed, query the employee. Both could take several seconds to complete particularly if they require downloading data over a network, but couldn't we save time by running them both simultaneously? Not only that, the user interface (UI) becomes unresponsive as all this code is being executed on the UI thread, this means the user has no way of cancelling the operation and no status is displayed to show what the application is actually doing.
Asynchronous
Asynchronous code is where a program will continue execution even before a particular operation has finished. When that operation does finish, specific code will be executed. This can be achieved by using event handlers or perhaps a loop that checks to see if the operation has finished, if it has, execute the handler code, if not then refresh the screen or handle user input. With the new async / await syntax programs can not only be asynchronous, but can be written just like it would be if it was synchronous. This makes the code much easier to follow depsite being more complicated behind the scenes.
Let's take a look at an asynchronous implementation of the example above.
method-id GetEmployeeDetailsAsync (id as binary-long) yielding employee as type EmployeeDetails async. declare account as type UserAccount invoke await type Task::WhenAll( delegate set account to GetUserAccount() end-delegate, delegate set employee to QueryEmployee(id) end-delegate) if not account::HasAccessRights(employee) raise new AccessDeniedException() end-if end method. method-id btnGetEmployee_Click (sender as object, e as type EventArgs) async-void. set lblStatus::Text to "Fetching employee" set btnGetEmployee::Enabled to false try declare employee = await GetEmployeeDetailsAsync(binary-long::Parse(txtId::Text)) invoke ShowEmployeeDetails(employee) catch ex as type Exception set lblStatus::Text to ex::Message finally set lblStatus::Text to "" set btnGetEmployee::Enabled to true end-try end method.
The Task Parallel Library (TPL) is an API from the .NET framework which can be used to write asynchronous code. In the snippet above, TPL calls are generated by the COBOL compiler when invoking GetEmployeeDetailsAsync
. This is achieved by awaiting GetEmployeeDetailsAsync
from an async-void method. When the await is hit, GetEmployeeDetailsAsync
is executed up until the first await call within that method. At that point, GetUserAccount
and QueryEmployee
are run simultaneously on separate threads using one of the TPL utility methods: Task::WhenAll
, while the UI thread returns back to the application loop. When both the employee details and the user account have been fetched, the execution of GetEmployeeDetailsAsync
continues (by default on the UI thread).
In order to achieve this behaviour in previous versions of Visual COBOL, a callback (delegate) would be required, but thanks to the new async syntax the method can still be written like a synchronous method, yet behind the scenes it is compiled to be asynchronous. This is known as a coroutine, another example being iterator methods.
The Task asynchronous programming model in C# Microsoft documentation covers .NET asynchronous programming in more depth.
Afterword
The new async
/ await
syntax now makes it easy to create asynchronous APIs for COBOL applications or C# applications to consume thus saving time and computation power. If an application is running in the cloud this can also mean saving money in CPU time or increasing the web traffic throughput.
It further illustrates Micro Focus' ongoing commitment to enhancing the COBOL language. Note that this is currently only available in our latest release of Visual COBOL for .NET technology.
Visual COBOL is available as a 30-day free trial, visit our product page for more information.