Sign in Join
Wiki copytemporary

Main Loop Hooks/zh CN: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## 问题陈述
22
33当你需要等待一些事件(如:socket、pipe...)的触发,在不阻塞主线程(main thread GUI)显示而又不使用多线程方式,反馈到主线程时。解决方法是把事件监视挂接(handles)到主事件循环中。
44
55## 结决的详细内容
66
77在单元文件 [[doc:lcl/lclintf|LCLIntf]] 中 2 个函数用来实现这个功能,如下:
88
9-`AddEventHandler(AHandle: THandle; AFlags: dword; `\
10-`    AEventHandler: TWaitHandleEvent; AData: PtrInt): PEventHandler;`\
11-`RemoveEventHandler(var AHandler: PEventHandler);`\
12-`SetEventHandlerFlags(AHandler: PEventHandler; NewFlags: dword);`
9+``` pascal
10+AddEventHandler(AHandle: THandle; AFlags: dword;
11+ AEventHandler: TWaitHandleEvent; AData: PtrInt): PEventHandler;
12+RemoveEventHandler(var AHandler: PEventHandler);
13+SetEventHandlerFlags(AHandler: PEventHandler; NewFlags: dword);
14+```
1315
1416类[[doc:lcl/interfacebase/twaithandleevent.html|TWaitHandleEvent]] 定义于 单元文件 InterfaceBase 其定义如下:
1517
16-` TWaitHandleEvent = procedure(AData: PtrInt; AFlags: dword) of object;`
18+``` pascal
19+ TWaitHandleEvent = procedure(AData: PtrInt; AFlags: dword) of object;
20+```
1721
1822[[doc:lcl/lclintf/addeventhandler.html|AddEventHandler]] 在主事件循环中添加一个事件监视挂接,当挂接被触发,作为 AData 参数传入的回调函数 ACallback 被调用,并传回相应的标志 Flags 信息,包含操作系统指定的信息。回传标志 Flags 到 AddEventHandler 中可以用 SetEventHandlerFlags 修改。使用 AddEventHandler 返回的挂接指针 PEventHandler 被 RemoveEventHandler 用于停止此挂接监视。
1923
2024[[doc:lcl/lclintf/removeeventhandler.html|RemoveEventHandler]] 停止指定的挂接监视。RemoveEventHandler 将把之前返回的 AHandler 设为nil, 此变量参数是 AddEventHandler 返回的指针(pointer)。
2125
2226### Windows
2327
2428在当前的实现中,AddEventHandler 里的 AFlags 参数未被使用, 在 TWaitHandleEvent 中 AFlags 被赋值为 0。
2529
2630Win32 支持以下的挂接监视类型, 基本上都被 MsgWaitForMultipleObjects 所支持:
2731
2832- change notifications (针对文件和文件夹)
2933- console input (控制台输入)
3034- events: signalled with SetEvent winapi function
3135- mutexes: signalled when it is not owned anymore
3236- processes: signalled when they terminate
3337- semaphore: signalled when it's *count* is greater than zero
3438- threads: signalled when they terminate
3539- timers: signalled when expired, see SetWaitableTimer
3640
3741### Gtk/Unix
3842
3943The AFlags parameter in AddEventHandler specifies the condition in which the handle should be signalled, with the possible values being the ones documented in the GIOCondition type in the [glib](http://developer.gimp.org/api/2.0/glib/glib-IO-Channels.html#GIOCondition) reference.
4044
4145In the callback, the AFlags will contain the condition, of the above referenced GIOCondition type, that was satisfied.
4246
4347Gtk/unix supports the following handle types:
4448
4549- files
4650- sockets
4751- pipes
4852
4953Note that win32 does not support sockets or pipes (at least, their use is "discouraged" by MSDN). Suggestion: use WSAEventSelect to create an event associated with a socket and pass the event handle.
5054
5155### Pipes 和 Process 的终止
5256
5357由于要提供交叉平台的解决方法针对 Pipes(Win32 不支持) 和 Process(gtk/unix 不支持),所附加的函数如下:
5458
55-`TChildExitReason = (cerExit, cerSignal);`\
56-`TPipeReason = (prDataAvailable, prBroken, prCanWrite);`\
57-`TPipeReasons = set of TPipeReason;`\
59+``` pascal
60+TChildExitReason = (cerExit, cerSignal);
61+TPipeReason = (prDataAvailable, prBroken, prCanWrite);
62+TPipeReasons = set of TPipeReason;
5863
59-`TChildExitEvent = procedure(AData: PtrInt; AReason: TChildExitReason; AInfo: dword) of object;`\
60-`TPipeEvent = procedure(AData: PtrInt; AReasons: TPipeReasons) of object;`
64+TChildExitEvent = procedure(AData: PtrInt; AReason: TChildExitReason; AInfo: dword) of object;
65+TPipeEvent = procedure(AData: PtrInt; AReasons: TPipeReasons) of object;
66+```
6167
62-`function  AddProcessEventHandler(AHandle: THandle; `\
63-`    AEventHandler: TChildExitEvent; AData: PtrInt): PProcessEventHandler;`\
64-`procedure RemoveProcessEventHandler(var AHandler: PProcessEventHandler);`\
68+``` pascal
69+function AddProcessEventHandler(AHandle: THandle;
70+ AEventHandler: TChildExitEvent; AData: PtrInt): PProcessEventHandler;
71+procedure RemoveProcessEventHandler(var AHandler: PProcessEventHandler);
6572
66-`function  AddPipeEventHandler(AHandle: THandle; `\
67-`    AEventHandler: TPipeEvent; AData: PtrInt): PPipeEventHandler;`\
68-`procedure RemovePipeEventHandler(var AHandler: PPipeEventHandler);`
73+function AddPipeEventHandler(AHandle: THandle;
74+ AEventHandler: TPipeEvent; AData: PtrInt): PPipeEventHandler;
75+procedure RemovePipeEventHandler(var AHandler: PPipeEventHandler);
76+```
6977
7078When a process terminates the event handler specified will be called. AInfo will contain the exit code if AReason is cerExit, or (on unix only) the termination signal if AReason is cerSignal. For gtk/unix, use the PID to watch as AHandle. Internally, a signal handler is installed to catch the SIGCHLD signal. On win32, AddEventHandler is used to watch process termination.
7179
7280To watch a pipe for incoming data, pass the file descriptor (unix) or the pipe read-end handle to AddPipeEventHandler with a custom chosen event handler method as AEventHandler. On gtk/unix, AddEventHandler is called to watch the file descriptor for traffic. On win32, the message loop will timeout every 100 msecs to check all watched pipes for available data; if data is available, the event handler is called.
7381
7482---
7583*From the Free Pascal wiki, page "Main Loop Hooks/zh CN", as it stood on 2011-02-01 after a change by Chronos, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history