Performance issues while waiting for other programs

Hello,

I am using Borland C++ builder to create an application that will do the following:

Launch another program in execution (with CreateProcess()) and suspend the program flow until the launched program has finished executing. However, I don't want all flow to stop executing, just everything besides the GUI. If I use WaitForSingleObject(), the GUI also freezes until the program has finished. I want to be able to press a "stop" button that will instantly terminate the launched process. For this, I have the following, admittedly hackish solution:

Use _beginthread() to launch the function that does the program execution, have a variable done that is initially zero, then have a loop in the function that used _beginthread() : while (!done) Application->ProcessMessages; done will be set to 1 once the thread finishes.

This fixes the problem, at least for fast computers. On slower computers (not really slow, 2.0ghz P4 slow) not only does this also freeze the interface, it also makes the launched program run incredibly slow, making the whole thing freeze for a long time.

So, I'm open to any suggestions. How can I execute the program, suspend a certain function's execution until it finishes, keep the GUI responsive and now slow everything down?
DastasAsked:
Who is Participating?
 
itsmeandnobodyelseConnect With a Mentor Commented:
>>>> is this safe to do,
Yes it is safe. Any Windows program has a message loop similiar or identical. Heowever, you shouldn't forget the TranslateMessage as it calls PreTranslateMessage which gives a chance to suppress or transform messages for some important purposes, e. g. the TAB and ENTER key often were pretranslated by applications.
0
 
Jaime OlivaresSoftware ArchitectCommented:
0
 
itsmeandnobodyelseCommented:
>>>> while (!done)
If you would put a

   Sleep(100);  // wait 100 msec to give other processes a chance

in the while block, the screen wouldn't freeze.
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
DastasAuthor Commented:
itsmeandnobodyelse:

That seem even less elegant to me. Also, doesn't Sleep make the whole program wait? So it WOULD freeze for 100 msec even on fast comps. Not really a solution...

jaime_olivares: will take a look and implement today and post back.
0
 
itsmeandnobodyelseCommented:
>>>> Also, doesn't Sleep make the whole program wait?
No, only the thread where it was called.

The method is called polling and is - though not being elegant - a often used, simple and clean solution. However in your case it might be not necessary. If I understand your code correctly, you were processing messages while waiting for the launched process to terminate. If so, why not simply return after starting the thread and let the normal message loop do the processing? You could evaluate the 'done' flag in all handlers which should not be invoked while the launched process was active.

BTW, the (normal) message loop itself is polling as well, and it has a little sleep included (in idle time processing) which prevents from consuming all CPU time (as your loop did which didn't pause).
0
 
DastasAuthor Commented:
jaime_olivares:

I have implemented that, and it's not working as I need it to. It doesn't lag or anything, but I also have some timers in place that time the program's execution and auto-terminate it in case it exceeds a time limit. The method presented in that question bugs those timers (I assume because of the way MsgWaitForMultipleObjects() works...). Is there any way around this? Perhaps if I create a thread, MsgWaitForMultipleObjects() on the thread handle and start the process from the thread and use normal WaitForMultipleObjects() there? Would this allow my executed program and my termination conditions to run correctly?

itsmeandnobodyelse::

You are correct about Sleep, I'm sorry. Also correct about the method, if I do this:

            while ( !done )
            {
                  Sleep(100);
                  Application->ProcessMessages();
            }

The lag is reduced, however I don't like that I can still see when the GUI freezes for a short while. Also, I'm not sure how this would behave on slower computers...

Isn't there a better way?

". If I understand your code correctly, you were processing messages while waiting for the launched process to terminate. If so, why not simply return after starting the thread and let the normal message loop do the processing?"

I'm not sure how I would go about doing this. My process-launching thread is started in a for-loop, and after the thread start, I have the while ( !done ) loop. If I don't have this while loop, the for loop will keep launching threads, and I don't want that. Perhaps it's easier to understand what I mean if I tell you exactly what I'm working on. It's a specialised benchmarking program that executes other programs that work on some files, and then it compares results, then launches the same program on another data set and so on for a number of times. Each execution is timed and results are reported after each execution for that execution.
0
 
itsmeandnobodyelseCommented:
>>>> I'm not sure how I would go about doing this.
I assumed a normal Windows program which is message driven. Then, it has a message loop in the main thread like that

   while (PeekMessage(msg))
   {
           GetMessage(msg);
           TranslateMessage(msg);
           DispatchMessage(msg);
   }

In the DispatchMessage message handlers were called, e. g. after a button was clicked by the user.

None of the handlers may call sleep or message handling was paused, the screen freezes. If you need to do lengthy jobs, you have two choices: either break the jobs down to smaller parts and fastly return to the message loop after handling that part *or* put the the execution of the lengthy handling into a thread. The thread must not consume all CPU but should make sleeps in order to give other threads some CPU time. Instead of sleeps it also could wait for events what would slow down the thread as well and - if made clever - is a most elegant way - though not always makeable.  Note, the main thread in this scenario is a reactive thread. As far as I understand your app, you actively has to call Application->ProcessMessages() what is much more difficult to get into balance. If using threads you need synchronization when displaying results. You normally do that by calling PostMessage which is a thread-safe way to communicate between worker thread(s) and main thread. You also can have separate queue containers for each thread to send/receive jobs, messages, results. Then, you have to synchronize access to the queue(s) by using a mutex or critical section which makes the access exclusively, thus thread-safe.
0
 
DastasAuthor Commented:
I used this and it seems to work perfectly even on slow computers (no lag or freeze on 1.4 ghz processors). My questions is, is this safe to do, or can it somehow fail in certain situations?

The meaning of the done variable remains the same, and the threading scheme I explained in my first post:

            while ( !done )
            {
                  if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
                        DispatchMessage(&msg);
            }
0
 
DastasAuthor Commented:
Ok, thank you. I have awarded the points.
0
All Courses

From novice to tech pro — start learning today.