GameInput 主要围绕轮询模型设计,但在某些情况下,异步通知应用程序会更佳。为此,IGameInput 接口提供了若干方法,用于注册在特定关注事件发生时被调用的回调函数。
在内部,GameInput 会对回调调度进行序列化,一次只执行一个回调。GameInput 会保证按时间先后顺序调度回调。这些保证简化了应用程序在其回调函数中所需编写的代码。
无论回调类型如何,GameInput 允许在任意时刻最多注册 64 个回调。回调由 GameInput 内部的工作线程调度。有关其工作原理以及手动调度此工作的方式,请参阅 GameInput 工作队列。
设备回调
设备回调可让应用程序在输入设备状态发生变化时收到通知,其语法如下。最常见的场景是检测设备的连接与断开,但其他状态变化也可能值得关注。enumerationKind 参数接受来自 GameInputEnumerationKind 枚举的值,指示是否在回调注册过程中执行枚举,以及枚举应以阻塞方式还是异步方式执行。将设备枚举与后续状态变化合并为单一原子操作,可避免许多应用程序在输入代码中无意中出现的争用条件。
读取回调
通过读取回调,应用程序可以在输入流中有新的读取到来时收到通知,其语法如下。虽然许多应用程序会发现轮询输入更为合适,但仍存在某些情况下事件驱动的输入可能更佳。例如,游戏的主菜单 UI 可能更适合基于事件的输入。再如输入映射 UI,在提示用户选择后需要等待输入。注销回调
回调注册成功后,应用程序必须确保执行该回调所需的所有资源保持有效,包括回调代码所使用的资源以及回调函数本身,例如,回调函数托管在应用程序按需加载和卸载的 DLL 中的情形。 要安全回收这些资源,应用程序必须先注销回调,方法是将Register*Callback 方法返回的令牌传给 UnregisterCallback 方法。如果调用此方法时回调正在执行,则该方法会阻塞,直到回调执行完成。因此,回调不能在自己的回调函数内注销自身。
也可以通过调用 StopCallback 方法来停止回调。此方法不会注销回调,但可确保回调不再被调用。因为回调未被注销,所以从回调自身的回调函数中调用此方法是安全的。它会完成当前回调的执行,但不再调用该回调。回调最终仍必须注销,因为在任意时刻最多允许存在 64 个回调。
