0

I'm fairly new to IPC(interprocess communication). Doing my research, I decided on the Named pipes.
My application consists of 2 parts: a monitoring app, and a UI dashboard. The dashboard receives updates from the monitor constantly and shows stats, the user should be able to change certain parameters of the monitor through the dashboard (refresh rate, restart process,scheduled task...) so it has to be a bidirectional communication. The Monitor would later become a service application, but that's a plan for later.
Getting to the point, I used the Pipes unit by Overbyte(Francois Piette) v1.01 and followed the example made on their website. When connecting the pipes on the main thread, it functions normally. But due to my monitor needing a separate thread to (monitor-send message-sleep-loop...), when I try to connect on the other thread, I get an error "The notify window and the component window do not exist in the same thread!"

  • What I need to know is, can named pipes communicate using a separate thread? (Judging by the error msg, I feel it may be fetching the window handle on the main UI and would not work on a different thread)
  • Is there a better way to implement my application? or named pipes better than Overbyte?

Sample of my code:

TThreadMonitor = Class(TThread)
  private
    PipeClient1: TPipeClient;
    listOfProcesses: Array of String;
  protected
    procedure Execute; override;
  public
    constructor Create(CreateSuspended: Boolean);

    procedure ConnectPipe;
    procedure SendMessage(const Msg: String);
  End;

var
t: TThreadMonitor;

procedure TClientFormMain.BtnDifferentThreadClick(Sender: TObject);
begin
  t := TThreadMonitor.Create(TRUE);
  t.FreeOnTerminate := TRUE;

  t.Start;
end;

procedure TThreadMonitor.ConnectPipe;
begin
  if not PipeClient1.Connect(2000, TRUE) then
    LogThis('Pipe connection failed', LogFilePath, TRUE)
  else
    LogThis('Pipe connected', LogFilePath, TRUE);
end;

procedure TThreadMonitor.Execute;
begin
  inherited;

  ConnectPipe;  //<---throws exception here although getting "Pipe Connected"
    while not Terminated do
    begin
      for i := 0 to Length(listOfProcesses) - 1 do
      begin
        ...
        MonitorProcess(listOfProcesses[i]);
        ...
      end;
      sleep(2000);
    end;
end;
Alexander
  • 53
  • 1
  • 9
  • 1
    You did not show your code for the thread constructor, but I assume that is where you are creating your `TPipeClient` object instance, is that right? Do you have the same error if you create the instance inside the thread's `Execute()` method instead? – Remy Lebeau Dec 29 '16 at 20:04
  • 1
    AFAIU from browsing the source very little, the code is already threaded. See for instance TPipeClient.GetConnected/Connect, connection occurs in a TPipeThread. – Sertac Akyuz Dec 29 '16 at 20:09
  • 1
    Other than that, read the text on top of pipes.pas, it gives requirements for a pipe client component to be created in a thread. – Sertac Akyuz Dec 29 '16 at 20:11
  • @RemyLebeau Correct. Tried moving the PipeClient.create to the thread.create, I did not get the error! I also had to PipeClient.disconnect after each sendmessage – Alexander Dec 30 '16 at 19:55
  • Can you please explain a bit why this worked? – Alexander Dec 30 '16 at 19:56
  • 1
    @Alexander `TThread.Create()` and `TThread.Execute()` run in different threads. I'm not going to hunt down Overbyte's source code to check, but I assume from the error message that `TPipeClient` creates some internal windows and does not like when those windows are created in different threads. – Remy Lebeau Dec 30 '16 at 20:22

0 Answers0