Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2011-09

About Threads

5 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Kjow

Hi all,

I need to unlock my program when I run a function (it simply loads a file and elaborates some data, I would do something of beauty like a progress bar).
I read the wiki, but it seems to be too much for my purpose and the function I need to run is already inside a class (I wouldn't touch it).

On delphibasics I read about BeginThread (
http://www.delphibasics.co.uk/RTL.asp?Name=BeginThread ) and I'm trying to implement it on a trivial test project (it just insert in two TMemo the "i" of a loop), e.g.:

(********************************************)
...
function count(n: integer; memo: Tmemo):Integer;
var
  i: integer;
begin
  memo.Clear;
  for i:= 0 to n do
    begin
      memo.Append(IntToStr(i));
    end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
  count(1000,memo1);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
  count(1000,memo2);
end;
...
(********************************************)

The goal is to run "count" in a thread and BeginThread seems to be ok for this, but I have some problems with delphibasics code:

(********************************************)
...
function ShowMsg(Parameter : Pointer) : Integer;
begin
  // Set up a 0 return value
  Result := 0;
  // Map the pointer to the passed data
  // Note that each thread has a separate copy of msgPtr
  msgPtr := Parameter;
  // Display this message
  //ShowMessagePos('Thread '+IntToStr(msgPtr.thread)+' '+msgPtr.msg, //original
  //               200*msgPtr.thread, 100);
                              //original
  ShowMessagePos('Thread '+IntToStr(msgPtr^.thread)+' '+msgPtr^.msg,
                 200*msgPtr^.thread, 100);
  // End the thread
  EndThread(0);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
  id1, id2 : LongWord;
  thread1, thread2 : Integer;
  msg1, msg2 : TMsgRecord;
begin
  // set up our display messages
  msg1.thread := 1;
  msg1.msg    := 'Hello World';
  msg2.thread := 2;
  msg2.msg    := 'Goodbye World';
  // Start the first thread running asking for users first name
  thread1 := BeginThread(nil,
                         0,
                         Addr(ShowMsg), //I get error here(*)
                         Addr(msg1),
                         0,
                         id1);
  // And also ask for the surname
  thread2 := BeginThread(nil,
                         0,
                         Addr(ShowMsg), //I get error here(*)
                         Addr(msg2),
                         0,
                         id2);
  // Ensure that the threads are only closed when all done
  ShowMessagePos('Press this when other dialogs finished.', 200, 300);
  // Finally, tidy up by closing the threads
  CloseHandle(thread1);
  CloseHandle(thread2);
end;
...
(********************************************)
(*)I get error here: main.pas(122,31) Error: Wrong number of
parameters specified for call to "ShowMsg"

How to fix?

There is a better/easier way?

Thank you,
Kjow

Reply by email

Michael Schnell
to Kjow

The best (portable and avoiding "Windowish" stuff) way to notify the main thread about the state of a thread (so that the main thread can e.g. advance a progress bar without temporarily stall the worker thread is "Application. QueuAsyncCall()".

Same fires a procedure in the main thread and provides it with a parameter.

-Michael

Reply by email

Michael Schnell
Kjow wrote
Thank you for hint, but trying it the Form is too slow and semi-freezed.

QueuAsyncCall() does not considerably impact the Worker-Thread, so obviously you mean that the main (GU-)I thread gets slow.

Here of course the correct way is to do the QueuAsyncCall() not too often. (e.g. only when e.g. 5 % in the progress bar value is overrun)

-Michael

Reply by email

Michael Schnell
Kjow wrote 13 lines
2011/9/22 Michael Schnell: > QueuAsyncCall() does not considerably impact the Worker-Thread, so obviously > you mean that the main (GU-)I thread gets slow. > > Here of course the correct way is to do the QueuAsyncCall() not too often. > (e.g. only when e.g. 5 % in the progress bar value is overrun) > > -Michael I'm using a real-time 3D graphics on my project and while it loading I would generate some smooth animations, this is why I need something more "powerfull" :) Kjow

There is nothing more powerful. You just need to use the stuff provided in a decent way or give up.

-Michael

Reply by email

Michael Schnell
Kjow wrote
I'll try to investigate :)

If you really desperately need "something more powerful" I suppose the only way is to introduce a second GUI Window. This will might if you are using a multi-Core System.

Obviously it is possible to create a second GUI Windows by starting a second executable (and have same communicate with the main executable by means such as Windows Messages, Pipes and/or shared RAM.

It might (or might not) be possible to create a second GUI Windows by using the second copy of the LCL that is created by a DLL / *.so and create a second application with same in a thread. Bus as nobody did decently try this yet, you are on your own evaluating this. (See the recent thread on DLL in this forum) Let us know where you get.

-Michael

Reply by email