寻找进程间通信中使用的 Windows 消息的替代方案
我有一个多线程应用程序(MIDAS),它利用 Windows 消息与其自身进行通信。
MAIN FORM
主窗体接收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 消息缓冲区已满并且速度变慢
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
使用命名管道。 如果您不知道如何使用它们,那么现在是学习的时候了。
使用命名管道,您可以发送任何类型的数据结构(只要服务器和客户端都知道该数据结构是什么)。 我通常使用一组记录来来回发送大量信息。 非常便利。
我使用 Russell Libby 的免费(且开源)命名管道组件。 附带 TPipeServer 和 TPipeClient 可视组件。 它们使命名管道的使用变得异常简单,并且命名管道非常适合进程间通信(IPC)。
您可以在此处获取该组件 。 来源的描述是: // 描述:Delphi 的客户端和服务器命名管道组件集,如
// 一个控制台管道重定向组件。
此外,Russell 帮助我在 Experts-Exchange 上使用该组件的旧版本在控制台应用程序中工作,通过命名管道发送/接收消息。 这可能有助于指导您启动并运行他的组件。 请注意,在 VCL 应用程序或服务中,您不需要像我在这个控制台应用程序中那样编写自己的消息循环。
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.
方案一:自定义消息队列
您可以构建自定义消息队列,将消息推送到队列中,根据业务规则对队列进行排序,并从主线程中弹出队列中的消息进行处理。 使用关键部分进行同步。
选项 2:回调
使用回调在线程之间来回发送数据。 再次,使用临界区进行同步。
Option 1: Custom Message Queue
You can build a custom message queue, and push messages to the queue, sort the queue based on business rules, and pop messages from queue from the main thread for processing. Use a critical section for synchronization.
Option 2: Callbacks
Use callbacks to send data back and forth from the threads. Again, use a critical section for synchronization.
OmniThreadLibrary 在
OtlComm.pas
单元中包含非常高效的消息队列。目前文档还不是很好(从这里开始)但您始终可以使用论坛。
OmniThreadLibrary contains very efficient message queue in
OtlComm.pas
unit.Documentation is not very good at the moment (start here) but you can always use the forum.
是的 – Gabr,您可以在服务中使用 Windows 消息。
==============================
在 Windows Vista 之前,您可以将服务配置为与桌面交互。 这使得该服务与登录用户在同一桌面上运行,因此以该用户身份运行的程序可以向服务的窗口发送消息。 不过,Windows Vista 隔离了服务; 他们无法再与任何用户的桌面交互。
===============================
引用 Rob Kennedy 的回答到 'TService 不会处理消息'
但我将无法使用 'frmMain.Handle ' 将消息从 RDM 发布到 Windows Vista 中的主窗体。
我需要做的就是找到一种不同的发布方式和发布方式。 收到消息
Yes – Gabr you can use windows messages in a service.
==============================
Before Windows Vista, you could have configured your service to interact with the desktop. That makes the service run on the same desktop as a logged-in user, so a program running as that user could send messages to your service's windows. Windows Vista isolates services, though; they can't interact with any user's desktop anymore.
=============================
A Quote from Rob Kennedy answer to ‘TService won’t process messages’
But I will not able to use 'frmMain.Handle' to post messages from the RDM to the main form in windows Vista.
All I need to do is find a different way of posting & receive the message
Windows 消息仍然可以在 Windows Vista 中使用! 目前的问题是,vista 中的一项称为用户界面权限隔离 (UIPI) 的技术可防止完整性级别 (IL) 较低的进程向 IL 较高的进程发送消息(例如,Windows 服务具有较高的 IL 和用户权限)模式应用程序具有中等 IL)。
但是,这可以被绕过,并且可以允许中等 IL 应用程序将 wm 发送到高 IL 进程。
维基百科说得最好:
Delphi-PRAXIS 的某人(链接是德语。使用 Google 翻译页面)已经解决了这个问题,并使用 ChangeWindowMessageFilter 发布了他们的代码。 我相信他们的问题是 WM_COPYDATA 在 Vista 上无法工作,直到他们修改代码以绕过 WM_COPYDATA 的 UIPI。
原始链接(德语)
Windows Messages CAN still be used in Windows Vista! The issue at hand is that a technology in vista called User Interface Privilege Isolation (UIPI) prevents processes with a lower integrity level (IL) from sending messages to a proccess with a high IL (e.g. a windows service has a high IL and user-mode apps have medium IL).
However, this can be bypassed and medium IL apps can be allowed to send wm's to high IL processes.
Wikipedia says it best:
Someone over at Delphi-PRAXIS (link is in German. Use Google to Translate the page) has already tackled this problem and posted their code using ChangeWindowMessageFilter. I believe their issue is that WM_COPYDATA would not work on Vista until they modified their code to bypass UIPI for WM_COPYDATA.
Original Link (German)
madExcept 库等的创建者提供了可以用来代替 Windows 消息的 IPC 功能。
http://help.madshi.net/IPC.htm
我曾经开发过一个 Windows 屏幕保护程序阶段,我想让我的屏幕保护程序向另一个程序发送一些通知,当屏幕保护程序处于活动状态时,我无法获取在两个应用程序之间工作的窗口消息。
我用上面提到的IPC功能替换了它。
做了一份款待。
The creators of the madExcept library etc provide IPC functionality which can be used instead of Windows messages.
http://help.madshi.net/IPC.htm
I developed a Windows screensaver at one stage, and I wanted to get my screensaver to send some notification to another program, and while the screensaver was active, I was unable to get window messages to work between the two apps.
I replaced it with the IPC functionality mentioned above.
Worked a treat.
我将此库用于 IPc(使用共享内存+互斥体):
http://17slon.com/gp/gp/gpsync.htm
它有 TGpMessageQueueReader和 TGpMessageQueueWriter。 在名称前面使用“Global\”,这样当用户登录时,您可以使用它在 Windows 服务和“Service GUI Helper”之间进行通信。(Vista 需要 Global\ 前缀,因为会话安全环,也适用于 Windows XP/2003 用户会话之间)。
它非常快,多线程等。我会使用这个而不是 WM_COPYDATA (如果你经常使用它,速度慢且开销很大,但对于小事情消息可以是好的)
I use this library for IPc (uses shared memory + mutex):
http://17slon.com/gp/gp/gpsync.htm
It has TGpMessageQueueReader and TGpMessageQueueWriter. Use "Global\" in front of the name, so you can use it to communicate between a Windows Service and a "Service GUI Helper" when a user logs in. (the Global\ prefix is needed for Vista because of session security rings, but also for Windows XP/2003 between user sessions).
It is very fast, multithreaded, etc. I would use this one instead of WM_COPYDATA (slow & much overhead if you use it a lot, but for small things messages can be OK)