寻找用于进程间通信的 Windows 消息的替代方案 [英] Looking for an alternative to windows messages used in inter-process communication

查看:27
本文介绍了寻找用于进程间通信的 Windows 消息的替代方案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个多线程应用程序 (MIDAS),它利用 Windows 消息与自身进行通信.

I a have a multithread application (MIDAS) that makes uses of windows messages to communicate with itself.

主要形式

主窗体接收RDM发送的windows消息LogData(‘DataToLog’)

The main form receives windows messages sent by the RDM LogData(‘DataToLog’)

因为使用了windows消息,所以它们具有以下属性

Because windows messages are used they have the following attributes

  1. 收到的消息是不可分割的
  2. 收到的消息按发送顺序排队

问题:

你能提出一种不使用 Windows 消息的更好方法吗?

Can you Suggest a better way doing this without using windows messages ?

主表单代码

const
    UM_LOGDATA      = WM_USER+1002;

type

  TLogData = Record
      Msg        : TMsgNum;
      Src        : Integer;
      Data       : String;
  end;
  PLogData = ^TLogData;


  TfrmMain = class(TForm)
  //  
  private
    procedure LogData(var Message: TMessage);        message UM_LOGDATA;
  public
  //        
  end;


procedure TfrmMain.LogData(var Message: TMessage);
var LData : PLogData;
begin
    LData  :=  PLogData(Message.LParam);
    SaveData(LData.Msg,LData.Src,LData.Data);
    Dispose(LData);
end;

RDM 代码

procedure TPostBoxRdm.LogData(DataToLog : String);
var
  WMsg  : TMessage;
  LData : PLogData;
  Msg   : TMsgNum;
begin
  Msg := MSG_POSTBOX_RDM;
  WMsg.LParamLo := Integer(Msg);
  WMsg.LParamHi := Length(DataToLog);
  new(LData);
    LData.Msg    := Msg;
    LData.Src    := 255;
    LData.Data   := DataToLog;
  WMsg.LParam := Integer(LData);
  PostMessage(frmMain.Handle, UM_LOGDATA, Integer(Msg), WMsg.LParam);
end;

为什么我想摆脱 Windows 消息:

Why I want to get rid of the windows messages:

  • 我想将应用程序转换为 Windows 服务
  • 当系统繁忙时——windows 消息缓冲区已满,运行速度变慢

推荐答案

使用命名管道.如果您不知道如何使用它们,那么现在是学习的时候了.

Use Named Pipes. If you don't know how to use them, then now is the time to learn.

使用命名管道,您可以发送任何类型的数据结构(只要服务器和客户端都知道该数据结构是什么).我通常使用一组记录来回发送大量信息.很方便.

With named pipes, you can send any type of data structure (as long as both the server and the client know what that data structure is). I usually use an array of records to send large collections of info back and forth. Very handy.

我使用 Russell Libby 的免费(和开源)命名管道组件.带有一个 TPipeServer 和一个 TPipeClient 可视化组件.它们使命名管道的使用变得异常简单,而且命名管道非常适合进程间通信 (IPC).

I use Russell Libby's free (and open-source) named pipe components. Comes with a TPipeServer and a TPipeClient visual component. They make using named pipes incredibly easy, and named pipes are great for inter-process communication (IPC).

你可以在这里获取组件.来自源码的描述是://描述 : Delphi 的客户端和服务器命名管道组件集,如//以及一个控制台管道重定向组件.

You can get the component here. The description from the source is: // Description : Set of client and server named pipe components for Delp as // well a console pipe redirection component.

此外,Russell 帮助我在 Experts-Exchange 上使用此组件的旧版本在控制台应用程序中工作,以通过命名管道发送/接收消息.这可能有助于指导您开始使用他的组件.请注意,在 VCL 应用程序或服务中,您不需要像我在此控制台应用程序中那样编写自己的消息循环.

Also, Russell helped me out on Experts-Exchange with using an older version of this component to work in a console app to send/receive messages over named pipes. This may help as a guide in getting you up and running with using his components. Please note, that in a VCL app or service, you don't need to write your own message loop as I did in this console app.

program CmdClient;
{$APPTYPE CONSOLE}

uses
  Windows, Messages, SysUtils, Pipes;

type
  TPipeEventHandler =  class(TObject)
  public
     procedure  OnPipeSent(Sender: TObject; Pipe: HPIPE; Size: DWORD);
  end;

procedure TPipeEventHandler.OnPipeSent(Sender: TObject; Pipe: HPIPE; Size: DWORD);
begin
  WriteLn('On Pipe Sent has executed!');
end;

var
  lpMsg:         TMsg;
  WideChars:     Array [0..255] of WideChar;
  myString:      String;
  iLength:       Integer;
  pcHandler:     TPipeClient;
  peHandler:     TPipeEventHandler;

begin

  // Create message queue for application
  PeekMessage(lpMsg, 0, WM_USER, WM_USER, PM_NOREMOVE);

  // Create client pipe handler
  pcHandler:=TPipeClient.CreateUnowned;
  // Resource protection
  try
     // Create event handler
     peHandler:=TPipeEventHandler.Create;
     // Resource protection
     try
        // Setup clien pipe
        pcHandler.PipeName:='myNamedPipe';
        pcHandler.ServerName:='.';
        pcHandler.OnPipeSent:=peHandler.OnPipeSent;
        // Resource protection
        try
           // Connect
           if pcHandler.Connect(5000) then
           begin
              // Dispatch messages for pipe client
              while PeekMessage(lpMsg, 0, 0, 0, PM_REMOVE) do DispatchMessage(lpMsg);
              // Setup for send
              myString:='the message I am sending';
              iLength:=Length(myString) + 1;
              StringToWideChar(myString, wideChars, iLength);
              // Send pipe message
              if pcHandler.Write(wideChars, iLength * 2) then
              begin
                 // Flush the pipe buffers
                 pcHandler.FlushPipeBuffers;
                 // Get the message
                 if GetMessage(lpMsg, pcHandler.WindowHandle, 0, 0) then DispatchMessage(lpMsg);
              end;
           end
           else
              // Failed to connect
              WriteLn('Failed to connect to ', pcHandler.PipeName);
        finally
           // Show complete
           Write('Complete...');
           // Delay
           ReadLn;
        end;
     finally
        // Disconnect event handler
        pcHandler.OnPipeSent:=nil;
        // Free event handler
        peHandler.Free;
     end;
  finally
     // Free pipe client
     pcHandler.Free;
  end;

end.

这篇关于寻找用于进程间通信的 Windows 消息的替代方案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆