寻找在进程间通信中使用的Windows消息的替代方法 [英] Looking for an alternative to windows messages used in inter-process communication
问题描述
MAIN FORM
$ b我有一个多线程应用程序(MIDAS)使用Windows消息与自己进行通信。 $ b
主窗体接收RDM发送的Windows消息
LogData('DataToLog')
由于使用Windows消息,它们具有以下属性
- 收到的邮件是不可分割的
- 收到的邮件按照发送的顺序排队
QUESTION:
你能建议一个更好的方法在不使用Windows消息的情况下执行此操作?
主表格代码
const
UM_LOGDATA = WM_USER + 1002;
type
TLogData = Record
Msg:TMsgNum;
Src:整数;
数据:字符串;
结束
PLogData = ^ TLogData;
TfrmMain = class(TForm)
//
private
程序LogData(var Message:TMessage);消息UM_LOGDATA;
public
//
end;
程序TfrmMain.LogData(var Message:TMessage);
var LData:PLogData;
begin
LData:= PLogData(Message.LParam);
SaveData(LData.Msg,LData.Src,LData.Data);
处理(LData);
结束
RDM代码
程序TPostBoxRdm.LogData(DataToLog:String);
var
WMsg:TMessage;
LData:PLogData;
消息:TMsgNum;
begin
Msg:= MSG_POSTBOX_RDM;
WMsg.LParamLo:=整数(Msg);
WMsg.LParamHi:=长度(DataToLog);
new(LData);
LData.Msg:= Msg;
LData.Src:= 255;
LData.Data:= DataToLog;
WMsg.LParam:=整数(LData);
PostMessage(frmMain.Handle,UM_LOGDATA,Integer(Msg),WMsg.LParam);
结束
编辑:
为什么我想摆脱Windows消息:
- 我想将应用程序转换为Windows服务
- 系统忙时,Windows消息缓冲区已满,事情减慢了
使用命名管道。如果您不知道如何使用它们,那么现在是学习的时候了。
使用命名管道,您可以发送任何类型的数据结构(只要服务器和客户端都知道该数据结构是什么)。我通常使用一系列记录来发送大量的信息。非常方便。
我使用Russell Libby的免费(和开源)命名管道组件。配有一个TPipeServer和一个TPipeClient可视化组件。他们使用命名管道非常简单,命名管道非常适合进程间通信(IPC)。
您可以在这里获取组件。来源的描述是://描述:为Delphi设置客户端和服务器命名的管道组件,如
//好的控制台管道重定向组件。
此外,Russell帮助我在Experts-Exchange上使用旧版本的此组件,在控制台应用程序中通过命名管道发送/接收消息。这可能有助于作为使用他的组件让您开始运行的指南。请注意,在VCL应用程序或服务中,您不需要像我在此控制台应用程序中编写自己的消息循环。
程序CmdClient;
{$ APPTYPE CONSOLE}
使用
Windows,Messages,SysUtils,Pipes;
type
TPipeEventHandler = class(TObject)
public
procedure OnPipeSent(Sender:TObject; Pipe:HPIPE; Size:DWORD);
结束
程序TPipeEventHandler.OnPipeSent(发件人:TObject;管道:HPIPE;大小:DWORD);
begin
WriteLn('On Pipe Sent已执行!');
结束
var
lpMsg:TMsg;
WideChars:WideChar的Array [0..255];
myString:String;
iLength:整数;
pcHandler:TPipeClient;
peHandler:TPipeEventHandler;
begin
//为应用程序创建消息队列
PeekMessage(lpMsg,0,WM_USER,WM_USER,PM_NOREMOVE);
//创建客户端管理程序
pcHandler:= TPipeClient.CreateUnowned;
//资源保护
尝试
//创建事件处理程序
peHandler:= TPipeEventHandler.Create;
//资源保护
尝试
//设置clien管道
pcHandler.PipeName:='myNamedPipe';
pcHandler.ServerName:='。';
pcHandler.OnPipeSent:= peHandler.OnPipeSent;
//资源保护
尝试
//连接
如果pcHandler.Connect(5000)然后
begin
//为管道客户端发送消息
while PeekMessage(lpMsg,0,0,0,PM_REMOVE)do DispatchMessage(lpMsg);
//设置发送
myString:='我发送的消息';
iLength:=长度(myString)+ 1;
StringToWideChar(myString,wideChars,iLength);
//发送管道消息
如果pcHandler.Write(wideChars,iLength * 2)然后
begin
//刷新管道缓冲区
pcHandler.FlushPipeBuffers;
//获取消息
如果GetMessage(lpMsg,pcHandler.WindowHandle,0,0)then DispatchMessage(lpMsg);
结束
end
else
//无法连接
WriteLn('无法连接到',pcHandler.PipeName);
finally
//显示完成
写('完成...');
//延迟
ReadLn;
结束
finally
//断开事件处理程序
pcHandler.OnPipeSent:= nil;
//自由事件处理程序
peHandler.Free;
结束
finally
// Free pipe client
pcHandler.Free;
结束
结束。
I a have a multithread application (MIDAS) that makes uses of windows messages to communicate with itself.
MAIN FORM
The main form receives windows messages sent by the RDM LogData(‘DataToLog’)
Because windows messages are used they have the following attributes
- Received messages are Indivisible
- Received messages are Queued in the order they are sent
QUESTION:
Can you Suggest a better way doing this without using windows messages ?
MAIN FORM CODE
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 CODE
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;
EDIT:
Why I want to get rid of the windows messages:
- I would like to convert the application into a windows service
- When the system is busy – the windows message buffer gets full and things slows down
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.
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).
You can get the component here. The description from the source is: // Description : Set of client and server named pipe components for Delphi, as // well a console pipe redirection component.
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屋!