Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c GCD和RunLoops_Objective C_Cocoa_Macos_Grand Central Dispatch - Fatal编程技术网

Objective c GCD和RunLoops

Objective c GCD和RunLoops,objective-c,cocoa,macos,grand-central-dispatch,Objective C,Cocoa,Macos,Grand Central Dispatch,在我的应用程序中,我将一个CFMachPortRef(通过CFMachPortCreateRunLoopSource)添加到线程CFRunLoop 现在我问自己,这可以用GCD来完成吗?假设不生成自己的NSThread并通过CFRunLoopAddSource将创建的CFRunLoopSourceRef添加到其运行循环,而是将事件端口添加到调度的runloop 我认为由于GCD的内部工作,这很可能不起作用,但我真的不知道 更新 到目前为止,我已经了解到了这一点,但是既没有调用事件tap的回调函

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

现在我问自己,这可以用GCD来完成吗?假设不生成自己的NSThread并通过CFRunLoopAddSource将创建的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);

实际上,您可以使用GCD来监控马赫数端口,使用
dispatch\u source\u 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提供的全局队列来处理消息,但如果愿意,可以创建自定义队列

要计划从GCD队列上的通知端口进行的回调,您可以使用,而不是使用带有Runloop的
CFRunLoopAddSource

例如:

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);

这将导致在GCD队列上调用
myCallback()
处理程序
myQueue
Invoke
dispatch\u resume
方法必须位于调用
mach\u msg
方法about
port
的同一线程中。你可以试试。

不起作用(至少在我的情况下):请参阅上面的更新部分。如果你发布了一条“不能用这种方式处理事件点击”,我可以接受你的回答:)我不太清楚为什么该代码不起作用,我实际上没有使用带有马赫端口的GCD事件源(我使用过其他类型的GCD源),所以我不确定为事件点击创建的端口是否有一些限制。您是否尝试过CFRunLoop方式来做事情,只是为了确保至少tap被正确创建并在该上下文中工作?是的,CFRunLoop方式按预期工作,只有GCD样式的实现不起作用。一个
CFMachPort
组合了一个马赫端口和一个回调。如果使用GCD只监视马赫数端口,则忽略回调。在事件点击的情况下,回调是核心图形的内部调用,可能会执行一些重要的操作(比如从端口接收Mach消息、解码消息以及调用回调)。