• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 188
  • Last Modified:

Thread question.

Hi,

I'm making an application that's making some reports from a FoxPro database (Query). Five separate statistics are involved. I want my user to be able to hit the Cancel button while processing the data, so I guess I need a thread here.
My question is twofold:
A) Can I (using threads) process the 5 processes at the same time?
B) How can I kill all threads at work to stop when my user hits the Cancel button.

What I have now is one thread, which defines an array of five threads, each processing another statistic. However, I have to WaitFor all these threads to end before I can show the result. When I use the WaitFor procedure, the application won't react on my Cancel button...

Can anybody give me an example of how I can do this?

Thanks!
0
lizzzard
Asked:
lizzzard
  • 3
  • 3
  • 3
  • +1
1 Solution
 
LischkeCommented:
Hi lizzzard,

I think you are on the right track. But I recommend to use the WinAPI WaitForMultipleObjects and give it a timeout of, say, 1 second to give back control to the application. Another way would be to define 5 events which are set each by the corresponding thread when it has finished its report. The "supervisor" thread can what for all the  events to be signalled before returning to the application while the app. still can respond to UI events and eventually cancel the threads.

Ciao, Mike
0
 
LischkeCommented:
Oops, typos: The "supervisor" thread can wait for all the events...
0
 
lizzzardAuthor Commented:
Thank again Mike..

One more question...
If I kill a thread, does it allways kill it's child-threads?
0
2018 Annual Membership Survey

Here at Experts Exchange, we strive to give members the best experience. Help us improve the site by taking this survey today! (Bonus: Be entered to win a great tech prize for participating!)

 
LischkeCommented:
No, when a thread finishes then spawned threads keep alive as they are in reality part of the process they run in. But if the process is stopped then all its threads are also stopped. If the thread being stopped is the last one in a process then the process is also stopped. This is because a process is just a thread with some addition properties.

Ciao, Mike
0
 
niknoxeCommented:
Hi,
first of all, do you want to kill them or end them. If you want to end them, setup your remote threads and lower their priority. Otherwise they may block your main thread waiting for the Cancel. The best way in my opinion is to have a special event set, when a cancel occurs. Inside each worker thread there are frequent calls to that event like: if WaitForSingleObject (killEvent,0) = WAIT_OBJECT_0 then exit;
This will bring your code the safe way out and you can clean up correct. Especially with databases this behaviour is proposed.
To guarantee that your main will not stop before all threads are gone, you post in the OnTerminate of each thread a message that decrements the count of running threads. if all are gone a flag is set, that allows to stop main.

This is working very well for me and has proved to be stable, especially with databases.

hope i could help you
0
 
lizzzardAuthor Commented:
NixNoxe,

When the user presses the Cancelbutton, I just want each thread processing a statistic to stop. Could you please work out a small example for the cancel event using the waitforsingleobject? I can't really figure out what to do.

Thanks,

Lizzzard

0
 
niknoxeCommented:
Hi,

these code fragments are extracted from one of my programs. I have declared my own types for most of the objects, so some functions are missing. (At least, a little work must be down ... :)

Some general tips:

RegisterWindowsMessage gives you a unique message for Communication ( the getMessage call)

Always use PostMessage in connection with sleep (0) AND Application.ProcessMessages. Hands off from using synchronized

this is usefull code. SetEvent has a return value and must not succedd the first time
    repeat sleep (10); until SetEvent (ShutEvent);

the mentioned hook is needed for some special messages, which are not processed to the WinMain of your program, if you think, you are missing a message, install a hook to your own app. then you will get almost each and everything. refer to the documentation for further details or mail again, I have to search a little longer for this...

the only allowed communication between your thread and the main app is message posting. Parameter Transfer can be handled via lparam. If this is not enough, use an array AND a Mutex Access is only possible if the Mutex is available, so reading and writing is synchronized. i.e. getMutex, write, PostMessage, Application.Processmessages, releaseMutex, Doinig it that way guarantees, that the other part of your app is already listening when you release the mutex. This is getting a little bit complex right now, I don't know what you need exactly...

O.K. Hope that you have a better idea now.

Frank

procedure Tform.FormCreate(Sender: TObject);
begin
  // main control
  ExitApp:= false; thrcnt:= 0;

  ShutEvent:= CreateEvent (nil, true, false, 'ShutDownExit');

  NotifyThread:= tnit.create (ShutEvent);

  // Application setup
  with Application do begin
    // assign proc handlers
    OnMessage:= AppMessage;
  end; // with Application
....

// message handler function
function Tform.processMessage (const wparam, lparam: longint; var   handled: boolean): integer;
var Point: TPoint;
begin
  handled:= true;
  result:= 0; // default result

  if CANCELBUTTONPRESSED
    repeat sleep (10); until SetEvent (ShutEvent);

  if wparam = NotifyThread.nitatom then begin // notify icon is calling
    case lparam of
      WM_MOUSEMOVE: begin
      end;
      WM_LBUTTONDOWN: begin
      end;
      WM_LBUTTONUP: begin
      end;
      WM_LBUTTONDBLCLK: begin
      end;
      WM_RBUTTONDOWN: begin
        GetCursorPos (Point);
        PopupMenu.Popup (Point.x, Point.y);
      end;
      WM_RBUTTONUP: begin
      end;
      WM_RBUTTONDBLCLK: begin
      end;
      WM_MBUTTONDOWN: begin
      end;
      WM_MBUTTONUP: begin
      end;
      WM_MBUTTONDBLCLK: begin
      end;
      WM_MOUSEWHEEL: begin
      end;
    else end; // case lparam
    exit;
  end;

  case wparam of //
    THREADCOUNTER: begin
      case lparam of
      INC_COUNTER: begin
        inc (thrcnt);
        ShowMessage (format ('Num threads %d', [thrcnt]));
      end;
      DEC_COUNTER: begin
        dec (thrcnt);
        ShowMessage (format ('Num threads %d', [thrcnt]));
        if thrcnt < 1 then begin
          ActionCloseExecute (Application.Mainform);
        end;
      end;
      else end; // case
    end;
  else begin
    handled:= false;
    result:= integer (false);
  end; end; // else case wparam

end;

procedure Tform.AppMessage (var Msg: TMsg; var Handled: Boolean);
begin   //
  handled:= false;
  with Msg do begin
    if Message = getMessage
      then processMessage (wparam, lparam, handled);
  end; // with msg
end; // proc

//
procedure Tform.WndProc (var Msg: TMessage); var handled: boolean;
begin
  with msg do begin
    if msg = getMessage
      then result:= processmessage (wparam, lparam, handled);
  end; // with
  inherited WndProc (Msg); // weitergabe
end; // proc

// application hook is also possible the same way


procedure waitthread.Execute;
var wres: integer;
function CanContinue: boolean;
begin
    wres:= WaitForSingleObject (ShutEvent, WAITTIME);
    if wres = TIMEOUT
      then CanContinue:= true
      else CanContinue:= false;
end;
begin;
  Do;
  if not CanContinue then exit;
  Do;
  if not CanContinue then exit;
  Do;
  if not CanContinue then exit;
  Do;
  if not CanContinue then exit;
  Do;
  // bye
  PostMessage (form.handle, form.GetMessage, THREADCOUNTER, DEC_COUNTER); //
  Application.ProcessMessages;
  sleep(0);
end;


They are communicating with Messages and control is done via events. The priority settings are done during creation of the thread.
0
 
gandalf_the_whiteCommented:
listening...
0
 
niknoxeCommented:
If you have further questions (there are some tricky things right in front of you), please contact me directly: niknoxe@hotmail.com.

best regards
0
 
lizzzardAuthor Commented:
Thanks!

I'm sure you'l hear from me...

Regards,

Lizzzard
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 3
  • 3
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now