WinForms and Threads
If you've done any programming in .Net, you're probably aware that accessing UI controls from a thread that didn't create the controls is a big no-no. One of the golden rules of using Winforms and Threading is that you don't touch anything created on one thread in another one.
But not everyone is aware that neither ADO.NET nor Winforms are thread safe. Plainly put, you can’t update a WinForm control from a callback or from another thread, and you need to ensure that ADO.Net objects are not touched in multiple threads at the same time, it’s not always very easy. Writing multi-threaded code that violates these rules can seem to work perfectly fine while testing on your machine, but might not work on the machine sitting next to it, or maybe it works on Monday but not on Tuesday...
On MSDN you can find this statement from Microsoft:
"Access to Windows Forms controls is not inherently thread safe. If you have two or more threads manipulating the state of a control, it is possible to force the control into an inconsistent state. Other thread-related bugs are possible as well, including race conditions and deadlocks. It is important to ensure that access to your controls is done in a thread-safe way."
And if you read a bit further you'd find this advice from Microsoft:
"When you use multithreading of any sort, your code can be exposed to very serious and complex bugs. For more information, see Managed Threading Best Practices before implementing any solution that uses multithreading. "
So what does this mean for a Clarion developer? After all every Clarion program is multi-threaded, in fact most are seriously multi-threaded. Well those of you who were part of the EA program for Clarion 6 surely remember the problems we ran into when you started opening lots of MDI windows on separate threads in a tight loop; the result was a deadlock or a GPF. We reproduced the problem in a small Visual C++ program and opened an incident with Microsoft. The test code we submitted would reliably crash the OS system kernel. We were quite pleased to submit the bug report in anticipation of a quick bug fix, thus solving the problem our developers were running into.
But it was not to be, our bug report was passed up the chain of support within Microsoft and finally reached the developers that work on the OS kernel. At long last we thought, now we'll see it fixed. But the problem was deemed too complex and risky to fix. At that point Microsoft acknowledged the problem and told us that the documentation for the API that we used to create MDI windows on their own thread, an API that had been available forever, would be changed to state that it was not thread safe. That made for a gloomy day in normally sunny South Florida.
So we were left on our own and it was time to make a decision, we could have chosen to either (a) tell our developers we were going to change our documentation to match the new Microsoft documentation and state that threaded MDI operations were not thread safe and should be avoided, or (b) find a way to fix the problem ourselves. We chose (b), and through a combination of complex modifications to the RTL, new language functions, helper classes and template code, we succeeded. Clarion Win32 programs can start new threads as fast as they want, they can communicate across threads, update the UI on other threads, and in general do about anything needed to get the job done.
But let’s get back to Winforms and threading. Since its common knowledge that WinForms are not thread safe what's a Clarion developer going to do in .Net? Well the answer from Microsoft would be to use threads very, very carefully, if at all.
From our side of the field there are some obvious choices, we could wrap all access to WinForms in the same fashion as we did for Clarion 6, or we could come up with something new that satisfied the needs of Clarion developers while avoiding the pitfalls of a single threaded UI model like WinForms.
There are two primary reasons why we Clarion developers like to use threads; performance related issues, we like to create responsive applications that don't put the user to sleep waiting for some report or process to complete, and secondly, we like to have multiple record buffers available to us.
Before I go any further let me make one thing crystal clear, you absolutely can write multi-threaded WinForm applications with Clarion.Net. The Start command is implemented, and so is the THREAD attribute, so you can happily create your multi-threaded applications in the same fashion as Clarion 6 (just with a bit more care). So with threading support already implemented in the Clarion.Net runtime we could have stopped right there as it satisfies both of our primary reasons to use threads.
But we didn’t stop there, you have a new option available in Clarion.Net; you can apply the TYPE attribute to a FILE! The TYPE attribute is already supported for the GROUP, QUEUE and CLASS structures, so why not a FILE structure? Its more exciting then it sounds, it opens up all kinds of opportunites.
In Clarion.Net the TYPE attribute on a FILE allows you to create instances of a FILE, as many instances as you like, and each instance gets its own Record Buffer. That means you can write code that opens multiple WinForms on the same thread, yet each "window" can have its own record buffer.
Clarion developers can have the best of both worlds, i.e. you can Start() as many threads as you need, and those threads can use threaded files, and you have the option to work with files on a single threaded UI. Or to put it another way, you can open multiple Browses on the same “typed” FILE, then open multiple Forms to update the Browses, each bit of code can work with a unique record buffer, and you can do it all on a single thread.
The use of typed files will be one of the options the .Net templates make available to you. Working with a FILE with the TYPE attribute is no different from one without it, aside from the bit of code to create a new instance of the FILE. However it does allow you to work safely and effectively within a single threaded UI.
SoftVelocity Inc.