6

The goal is to create communication between the two threads, one of which is the main thread. What I'm searching for is creating a window that takes less resource and use it to only receive messages.

What could you refer me to?

netboy
  • 343
  • 5
  • 11
  • 2
    You might want to have a look at [`AllocateHWnd`](http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Classes_AllocateHWnd.html). – Sertac Akyuz Aug 01 '11 at 16:14
  • @Sertac Akyuz, sorry, i hijacked your suggestion unintentionally, just noticed it after writing my own answer :-( – Premature Optimization Aug 01 '11 at 16:31
  • Downside of AllocateHwnd is that it's not threadsafe. Of course, this can be worked around. – David Heffernan Aug 01 '11 at 16:32
  • 1
    @Downvoter - No need to be sorry or to delete an answer. An answer is different than a comment. I commented because I've no intentions for following up, code sample etc.. Actually I think it might be a possible solution for the question. – Sertac Akyuz Aug 01 '11 at 16:53

3 Answers3

7

This is what message-only windows are for. I have written a sample Delphi send+receive system at a previous question.

Community
  • 1
  • 1
Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • Kind of makes this question a dupe, except that the linked question was so specific, and this one is general, and thus this question is more useful. Perhaps in such cases it would be better to just paste the entire code sample (duplicating it) here... Your thoughts?. – Warren P Aug 01 '11 at 23:23
7

What you need to do is set up a message loop in your thread, and use AllocateHWnd in your main thread to send message backward and forwards. It's pretty simple.

In your thread execute function have the following:

procedure TMyThread.Execute;
begin
  // this sets up the thread message loop
  PeekMessage(LMessage, 0, WM_USER, WM_USER, PM_NOREMOVE);

  // your main loop
  while not terminated do
  begin
    // look for messages in the threads message queue and process them in turn.
    // You can use GetMessage here instead and it will block waiting for messages
    // which is good if you don't have anything else to do in your thread.
    while PeekMessage(LMessage, 0, WM_USER, $7FFF, PM_REMOVE) do
    begin
      case LMessage.Msg of
      //process the messages
      end;
    end;

    // do other things. There would probably be a wait of some 
    // kind in here. I'm just putting a Sleep call for brevity
    Sleep(500);

  end;
end;

To send a message to your thread, do something like the following:

PostThreadMessage(MyThread.Handle, WM_USER, 0, 0);

On the main thread side of things, set up a window handle using AllocateHWnd (in the Classes unit), passing it a WndProc method. AllocateHWnd is very lightweight and is simple to use:

TMyMessageReciever = class
private
  FHandle: integer;

  procedure WndProc(var Msg: TMessage);

public
  constructor Create;
  drestructor Destroy; override;

  property Handle: integer read FHandle;

end;

implementation

constructor TMyMessageReciever.Create;
begin
  inherited Create;
  FHandle := Classes.AllocateHWnd(WndProc);
end;

destructor TMyMessageReciever.Destroy;
begin
  DeallocateHWnd(FHandle);
  inherited Destroy;
end;

procedure TMyMessageReciever.WndProc(var Msg: TMessage);
begin
  case Msg.Msg of
  //handle your messages here
  end;
end;

And send messages with either SendMessage, which will block till the message has been handled, or PostMessage which does it asynchronously.

Hope this helps.

Nat
  • 5,414
  • 26
  • 38
  • 3
    Alternatively, you don't really need `AllocateHwnd()` on the main thread, especially if you want to reduce resources. Use `PostThreadMessage()` to post messages directly to the main thread message queue using the `MainThreadID` variable as the target thread ID, then use the `TApplication.OnMessage` event to receive the messages. You can distinquish a thread message from a window message by looking at the `TMsg.hwnd` member, which will be zero for thread messages. – Remy Lebeau Aug 01 '11 at 22:02
  • Tried both, but none worked on a console app. My code --> http://pastebin.com/jm5K4EHN – netboy Aug 02 '11 at 10:55
  • I didn't realise you were in a console app... I see the problem in your code... You aren't checking the message queue periodically to see if there are any messages... You code is just sitting on the Readln. For the 'non-console' app, you need to call Application.Process messages periodically. In the console version you need a message pump. I think you should look at Andreas' example, it does precisely what you want to do. – Nat Aug 03 '11 at 03:40
2

In OmniThread Library by Gabr offers a nice little unit DSiWin32, you use that to create message windows, or you can just use OmniThread to do the communication for you.

Darkerstar
  • 924
  • 1
  • 8
  • 17