Evolving the Clarion Language

Nuts and bolts of the language changes made for .NET

<November 2006>
SuMoTuWeThFrSa
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

News

Current news on the nuts and bolts of the language changes made for .NET

Navigation

Subscriptions

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.

posted on Wednesday, November 15, 2006 1:06 PM by Robert Zaunere

# re: WinForms and Threads @ Wednesday, November 15, 2006 10:16 AM

Bob,

The TYPE attribute for FILE sounds really nice! Does this have any effect on the Access: and Relate: objects currently used in ABC?

On a secondary question, any plans on adding the TYPE attribute to WINDOW and REPORT? I would think for the same threading issues you mentioned.

Can't wait to see this product, hurry it up will ya? ;-)

Russ Eggen

Russell Eggen

# re: WinForms and Threads @ Wednesday, November 15, 2006 2:30 PM

Hi Russ,

Right now this feature is only planned for Clarion.NET, and is not applicable to C7.

As far as the WINDOW is concerned, no such animal exists in Clarion.NET, so again it is not applicable.

Regards!

Bob Foreman

# re: WinForms and Threads @ Wednesday, November 15, 2006 6:52 PM

Hi Bob,
really interresting stuff !!

Although, I don't know if I'm missing something, but you can easily access(update) Winform's controls created on another thread.

In fact, the .NET Framework 2.0 leverage this, and threading in general, from prior versions of the FrameWork.

The key here is to use one of the "Invoke" methods(Invoke, BeginInvoke, EndInvoke and CreateGraphics). The WinForm's controls expose a property called "InvokeRequired". You then know if you can update the control directly(called from the same thread [Control.InvokeRequired = False]) or if you need to "invoke"[Control.InvokeRequired = True] to avoid cross threading operation...which can result in a "CrossThreadException" (new in 2.0 to easily nail down those coding errors :) ) ...

Also, the "SyncLock" and the System.Threading namespace exposes a lot of synchonization objects which are quite easy to implement.

But, you are right the developper must ensure that it is done in a thread-safe manner...We did a lot of multi-threaded applications, some are really thread intensive and it is not so painful :¬)

But hey...that is why Clarion is so nice.
Wishing the best success to Clarion.NET !!!

My 2 cents :)


Pat Boisclair

# re: WinForms and Threads @ Thursday, November 16, 2006 7:26 AM

Hi Pat,

You're 100% on target, the "invoke" methods are what I was referring to when I said "just with a bit more care". Cross thread UI work can be done, but it requires some careful coding.

A developer may often need to start a separate thread for performance reasons, but other times you just need a new (unique) instance of a FILE and its record buffer, and do the work within the single UI thread. So with the advent of typed files you can easily have it both ways.

Robert Zaunere

Powered by Community Server, by Telligent Systems