在我的应用中,我将 CFMachPortRef (通过 CFMachPortCreateRunLoopSource )添加到线程 CFRunLoop
现在我问自己,这可以用GCD完成吗?假设不是通过 CFRunLoopAddSource 生成我自己的 NSThread 并将创建的 CFRunLoopSourceRef 添加到其运行循环中,而是将事件端口添加到调度的runloop中?
我认为由于GCD的内部运作,这很可能不会奏效,但我真的不知道。
更新
到目前为止我得到了这个,但是没有调用事件tap的回调函数和dispatch_source_event_handler块。有什么想法吗?
CFMachPortRef port = CGEventTapCreate(kCGSessionEventTap,
kCGHeadInsertEventTap,
opts,
desc_.eventMask,
_CGEventCallback,
self);
// create dispatch source
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV,
CFMachPortGetPort(port),
0,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
// set event handler
dispatch_source_set_event_handler(source, ^{
printf("handle me!\n");
});
dispatch_resume(source);
答案 0 :(得分:2)
您可以使用dispatch_source_create()
功能实际使用GCD监控Mach端口。代码看起来像这样:
mach_port_t myPort; //assume you have this already
dispatch_source_t portSource;
portSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, myPort, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT));
dispatch_source_set_event_handler(portSource, ^(void) { //code for handling incoming message here });
dispatch_resume(portSource);
每当有消息进入端口时,应该调用作为事件处理程序传入的块,并且可以在那里处理消息。此示例仅使用GCD提供的全局队列来处理消息,但您可以根据需要创建自定义队列。
答案 1 :(得分:0)
要从GCD队列上的通知端口安排回调,您可以使用IONotificationPortSetDispatchQueue而不是将CFRunLoopAddSource
与Runloop一起使用。
示例:
IOServiceOpen(driver, mach_task_self(), 0, &connection);
notifyPort = IONotificationPortCreate(kIOMasterPortDefault);
IOServiceAddInterestNotification(
notifyPort,
driver,
kIOGeneralInterest,
myCallback,
NULL, //refcon
¬ificationObject
);
// Instead of this:
// CFRunLoopAddSource(CFRunLoopGetCurrent(),
// IONotificationPortGetRunLoopSource(notifyPort),
// kCFRunLoopDefaultMode);
// do this:
IONotificationPortSetDispatchQueue(notifyPort, myQueue);
这将导致在GCD队列myCallback()
上调用myQueue
处理程序。
答案 2 :(得分:0)
调用dispatch_resume
方法必须在与调用mach_msg
的{{1}}方法相同的线程中。您可以尝试。