Fabrice Harari International WinDev Consultant

Home         About Fabrice         WinDev Files        Products        Fabrice's blog         Consulting        Contact Fabrice        Links

My status

Random errors: what can cause them

Multitask:
I didn't test this in WinDev 7/8/9, but under WinDev 5.5, you can achieve some quite interesting spider web using multitask and events... I suppose that you can generate the same kind of problems under the last version of WinDev, and that one answer to that problem is the new function MultitaskRedraw...

{AmazonLinks}


There is a reason why the Help file tells you that you should never use Multitask in an event code... The only problem is that it's not enough to be on the safe side...

First, let's see what's happening when you use a multitask -1 to interrupt a process, which is a legitimate way to code, as long as you are careful: In your main process loop, you are going to write something like:
multitask(-1)
if gwbInterruptRequested=true then...
and in the then, you are going to write the code necessary to end your process cleanly
At the same time, in the window where this process occurs, you will have grayed all the controls except the interrupt button, in which the only code will be:
gwbInterruptRequested=true

When you are doing that, your main process loop is interrupted each time you reach the multitask(-1), and if the user has previously clicked on the interrupt button, the click event will fire and your interrupt button code will be executed. At the end of this code, your main process code will continue at the line just after the multitask (i.e. the test on the flag)...

Problems are starting as soon as you deviate from that very simple schema... First, if you put mode code in your button than just setting a flag.... And the problem is to define precisely what MORE code means... At some point, when the number of line executed (and therefore when the execution time) exceed some limit, the main process will NOT restart at the line following the multitask... It looks like the return address was lost somewhere... You have therefore a code that was interrupted and never finished, and if you were allocating dynamic objects in that code, you didn't have the chance to delete them... Here is your memory leak...

That case is quite simple and easy to find, just remember not to have any lengthy code in that button (or in a procedure called fro that button).

But thinks are getting more complicated when you are not doing more complex process... Let's say that you are have multiple windows open at any given time (like any modern UI does), and that you are using events in some of them (by example to process the resizing on the fly, detect the click on a table column, etc...)... And now you have this lengthy process in one window and you want to display the content of the record currently processed... The normal way to achieve that is to do a multitask() (no minus sign this time) in your process, just after you set the value you want to display in a window field...

The one thing that is NOT written in any help file I'm aware of is that when the code encounter a multitask, events are firing... Which means that if during your process, the user TRIED to resize a window, or clicked on a table column, these events that were quietly waiting to be processed are going to be processed now, in the middle of your normally not interruptible code... At least some of them will... And depending of the length of the event management code, the program will continue or NOT at the line following the multitask...

And that's not the end of it... Till now, we just had one process interrupted, and possibly some objects not cleaned in memory, so nothing TOO bad (except that your process never finished of course :-)

But what happen when all that is part of the same class? More precisely, what happen when one dynamic object was running the main process in one of its methods, and when the event management is executed in another of its methods... Of course, I'm not aware of any inside information on the WinDev compiler (or should I say interpreter), but I have done enough work both on compilers in general and with WinDev to have a good idea on how things are organized... Each instantiated object clearly has internal pointers, stack of calls, and so on... It can be organized in one general stack or with one stack per object, but still, any compiler/interpreter needs to keep track of the returning address for each call of a method.... Let's have a look at what this kind of stack looks like when the main process has been called, and when it has called a secondary process:
The stack will obviously contain a return address for main process, and as the external event is also calling a method in the class, another returning address for this call... So when the event code doesn't return to the main process, what happen to the object stack and pointers? They still contain some information that is not accurate anymore... The funny part with that one is that not only the error message doesn't appear immediately, but depending of what process is called after that, you can in certain cases have a program working perfectly well... And in others crashing 10 minutes later...

 

Google
 
Web www.fabriceharari.com
Links:


Last modified Friday, March 17, 2006 12:10 PM central time