Solved

Performance issues while waiting for other programs

Posted on 2008-10-06
10
417 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
  • 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
 
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
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 

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

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

A short article about a problem I had getting the GPS LocationListener working.
Although it can be difficult to imagine, someday your child will have a career of his or her own. He or she will likely start a family, buy a home and start having their own children. So, while being a kid is still extremely important, it’s also …
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.

759 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now