1

过去,我使用了允许我注册回调的库,以便库可以在某些事件发生时调用我的方法(例如,在使用 GUI 库的代码中很常见button.onClick(clickHandler))。

天真地,我认为图书馆的处理机制可以像这样实现:

while(1){
  if (event1) { event1Handler(); }
  if (event2) { event2Handler(); }
  ...
}

但这真的很浪费,对吧?或者这真的是如何完成的(例如众所周知的 GUI 库,如 java swing,或 GTK+ 就是这样做的)?

背景:

直到我遇到curses才真正想到这个问题。我考虑过实现自己的回调系统,直到我意识到我不知道怎么做。

4

2 回答 2

2

while 循环通常会等待用户的中断(Windows 中的 GetMessage)。当中断到达时,GetMessage 返回,然后在回调函数中结束。if 语句通常实现为 switch-case。请参阅 Wikipedia 上的 Windows 消息循环。

更详细地说,会发生以下情况:

用户应用程序调用 GetMessage,它强制进程休眠,直到该应用程序的输入消息从系统队列中到达。当消息到达时,用户应用程序调用 DispatchMessage,后者调用与消息所针对的窗口关联的回调函数。

Windows API 使用一个回调来处理 switch case 中的所有事件。其他库改为对每个事件类使用一个回调。

函数指针本身与其他窗口数据一起存储在结构中。

于 2012-05-29T11:54:26.910 回答
0

回调系统实现可能在不同的技术中有不同的实现,但是,我想他们应该这样工作:

  1. 数据结构存储回调 ID 和指向处理程序的指针。

  2. 回调处理程序有一个验证器

  3. 事件处理程序有回调调用者,它们知道什么是可能的回调并以这种方式检查它们的有效性:

    对于 event.callbacks 中的每个回调

    if (callback.isValid())
    
        call callback()
    
    end if
    

    结束

  4. 当您向函数添加处理程序时,系统将自动知道回调在哪里有效,并将回调添加到 1 中描述的数据结构中。

如果我错了,请纠正我,这个描述只是一个猜测。

于 2012-05-29T11:58:53.230 回答