2

在我的应用程序中,我将CFMachPortRef(通过CFMachPortCreateRunLoopSource)添加到线程CFRunLoop

现在我在问自己,这可以使用 GCD 完成吗?假设不是生成我自己的NSThread并通过CFRunLoopAddSource将创建的CFRunLoopSourceRef添加到其运行循环中,而是将事件端口添加到调度的运行循环中?

我认为由于 GCD 的内部工作原理,这很可能不起作用,但我真的不知道。

更新


到目前为止我得到了这个,但是事件点击的回调函数和 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);
4

3 回答 3

2

您实际上可以使用 GCD 来监控 Mach 端口,使用该dispatch_source_create()功能。代码看起来像这样:

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 提供的全局队列来处理消息,但您可以根据需要创建自定义队列。

于 2010-07-15T16:11:40.700 回答
0

要从 GCD 队列上的通知端口安排回调,您可以使用IONotificationPortSetDispatchQueue而不是CFRunLoopAddSource与 Runloop 一起使用。

例子:

IOServiceOpen(driver, mach_task_self(), 0, &connection);

notifyPort = IONotificationPortCreate(kIOMasterPortDefault);

IOServiceAddInterestNotification(
  notifyPort,
  driver,
  kIOGeneralInterest,
  myCallback,
  NULL, //refcon
  &notificationObject
);

// Instead of this:
// CFRunLoopAddSource(CFRunLoopGetCurrent(),
//                    IONotificationPortGetRunLoopSource(notifyPort),
//                    kCFRunLoopDefaultMode);
// do this:
IONotificationPortSetDispatchQueue(notifyPort, myQueue);

这将导致myCallback()处理程序在 GCD 队列上被调用myQueue

于 2016-04-19T06:29:29.523 回答
0

调用dispatch_resume方法必须在调用方法的同一线程mach_msgport。你可以试试看。

于 2020-08-15T15:02:58.433 回答