1

I am creating a thread using BeginThread.

In the procedure I am using to start the thread I want to pass a pointer to a boolean variable so that both the forked thread and main thread can access it as a control variable to tell one when the other is done.

Since begin thread takes in a pointer for the parameters i have tried to pass in the Addr(MyPointerVar) but I am getting errors.

But I have to run so I cannot finish my thoughts here tonight. But if anyone has any ideas on doing this I appreciate it.

Tim
  • 1,549
  • 1
  • 20
  • 37
  • I am no longer getting errors but I still do not have the functionality I need yet. The pointer I get from inside the forked thread is not pointing to the same location as the one I send in. – Tim Nov 05 '10 at 13:31
  • yes, it will be the same pointer value (or else Delphi's own `TThread` class would not work correctly), so you are obviously doing something wrong on your end. Please show your actual code. – Remy Lebeau Nov 05 '10 at 19:24
  • @Remy: That's my assessment as well, I'll recreate it in a new project and see if it still happens then post that code. – Tim Nov 08 '10 at 14:32
  • Yep, it worked in a new project just fine, I don't have the old code since last Friday I went in a slightly different direction. I'm not certain what was difference. The code I just wrote was what I recalled writing Friday. One thing that was different was the thread procedure was in a different object that where I was calling begin thread. If I have more time later I might try that to see. Thank you Remy for your time – Tim Nov 08 '10 at 14:55

2 Answers2

8

Use the '@' address operator to pass the variable's address to BeginThread(), eg:

var
  ThreadDone: Boolean;
  ThreadId: LongWord;
  ThreadHandle: Integer;

function ThreadFunc(PThreadDone: PBoolean): Integer;
begin
  ...
  PThreadDone^ := True;
  Result := 0;
end;

...

ThreadHandle := BeginThread(nil, 0, @ThreadFunc, @ThreadDone, 0, ThreadId);

With that said, another way for the main thread to check if the thread is done without using a separate variable is to pass the thread handle returned by BeginThread() to WaitForSingleObject() and see if it returns WAIT_OBJECT_0 or not:

var
  ThreadId: LongWord;
  ThreadHandle: Integer;

function ThreadFunc(Parameter: Pointer): Integer;
begin
  ...
  Result := 0;
end;

...

ThreadHandle := BeginThread(nil, 0, @ThreadFunc, nil, 0, ThreadId);
...
if WaitForSingleObject(THandle(ThreadHandle), 0) = WAIT_OBJECT_0 then
  finished...
else
  still running...
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thank you Remy, I am preferring the first way since I plan to do a second version where I pass an integer to make a progress bar. However, what I had before was very similar to what you are doing however the address I pass in with @ThreadDone is a different address than I receive in parameter. – Tim Nov 05 '10 at 12:59
  • @Tim: please mark the answer by Remy as "accepted" by clicking on the check-mark next to it. – Jeroen Wiert Pluimers Nov 05 '10 at 13:10
  • Jeroen: I appreciate Remys answer and help but it has not answered my question fully. I must not have been clear in my comment above so I have added a comment to my question above that explains better. – Tim Nov 05 '10 at 14:26
  • @Tim: it is better to have the thread post notifications to the main thread for progress UI updates. Do not use pointers to shared variables for that. Have the thread use PostMessage() or PostThreadMessage(), and put the new status info in the WPARAM and LPARAM parameters as needed. The main thread's message loop can then process those notifications on its own time while the thread continues working. – Remy Lebeau Nov 05 '10 at 19:21
  • I wholeheartedly agree and appreciate your help, I will implement the solution using messages, although I am still gonna try to get it working the other way just to satisfy my curiosity. (and accept your answer shortly thereafter) – Tim Nov 08 '10 at 14:35
0

Remy's answer above is the correct solution.

I was doing what Remy has suggested above and was still having issues and with a quick test I just did it seems my fault was something dealing with having the threaded procedure in a different object than where beginthread was being called.

Tim
  • 1,549
  • 1
  • 20
  • 37