我有一个多线程应用程序(MIDAS)使用
Windows消息与自身进行通信.
主要形式
主窗体接收RDM发送的Windows消息
LogData(“DataToLog”)
因为使用Windows消息,它们具有以下属性
>收到的消息是不可分割的
>接收到的消息按照发送的顺序排队
题:
你可以建议一个更好的方法,而不使用Windows消息吗?
主编号
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消息:
>我想将应用程序转换为Windows服务
>当系统正忙 – Windows消息缓冲区已满,事情变慢
解决方法
使用命名管道.如果你不知道如何使用它们,那么现在是学习的时候了.
使用命名管道,您可以发送任何类型的数据结构(只要服务器和客户端知道该数据结构是什么).我通常使用一系列记录来发送大量的信息.很方便
我使用Russell Libby的免费(和开源)命名管道组件.配有一个TPipeServer和一个TPipeClient可视化组件.他们使用命名管道非常简单,命名管道非常适合进程间通信(IPC).
You can get the component here.源代码描述如下://说明:为Delphi设置客户机和服务器命名的管道组件,as
//很好的控制台管道重定向组件.
此外,Russell帮助我在Experts-Exchange上使用旧版本的这个组件,在控制台应用程序中通过命名管道发送/接收消息.这可能有助于作为使用他的组件让您开始运行的指南.请注意,在VCL应用程序或服务中,您不需要像我在此控制台应用程序中编写自己的消息循环.
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,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,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) 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.