Solved

Performance issues while waiting for other programs

Posted on 2008-10-06
10
447 Views
Last Modified: 2013-11-17
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?
0
Comment
Question by:Dastas
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 4
10 Comments
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 22666627
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 22668111
>>>> 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
 

Author Comment

by:Dastas
ID: 22668901
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
[Live Webinar] The Cloud Skills Gap

As Cloud technologies come of age, business leaders grapple with the impact it has on their team's skills and the gap associated with the use of a cloud platform.

Join experts from 451 Research and Concerto Cloud Services on July 27th where we will examine fact and fiction.

 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 22671169
>>>> 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
 

Author Comment

by:Dastas
ID: 22677920
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
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 22682554
>>>> 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
 

Author Comment

by:Dastas
ID: 22694309
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
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 500 total points
ID: 22694937
>>>> 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
 

Author Comment

by:Dastas
ID: 22701393
Ok, thank you. I have awarded the points.
0

Featured Post

Optimize your web performance

What's in the eBook?
- Full list of reasons for poor performance
- Ultimate measures to speed things up
- Primary web monitoring types
- KPIs you should be monitoring in order to increase your ROI

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Whether you’re a college noob or a soon-to-be pro, these tips are sure to help you in your journey to becoming a programming ninja and stand out from the crowd.
The SignAloud Glove is capable of translating American Sign Language signs into text and audio.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
Starting up a Project

632 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question