2010-07-15 46 views
2

在我的應用我添加CFMachPortRef(通過CFMachPortCreateRunLoopSource)的線程CFRunLoopGCD和RunLoops

現在,我問我自己,可以在此使用GCD做?比方說,而不是產卵我自己NSThread並通過CFRunLoopAddSource事件端口添加創建CFRunLoopSourceRef它的運行循環,增加調度的runloop?

我認爲這很可能不起作用,因爲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); 
+0

'CFMachPort'結合了Mach端口和回調。如果您使用GCD來監控Mach端口,則忽略回調。在事件點擊的情況下,回調在Core Graphics內部,大概是很重要的東西(例如接收來自端口的Mach消息,解碼並調用* your * callback)。 – 2016-03-13 21:50:40

回答

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提供的全局隊列來處理消息,但是如果你願意,你可以創建一個自定義隊列。

+0

不起作用(至少對於我的情況):請參閱上面的*更新*部分。 – 2010-07-16 11:59:09

+0

如果你發佈「不會用事件點擊這種方式工作」我可以接受你的答案:) – 2010-07-21 16:46:23

+0

我不完全確定爲什麼代碼不會工作,我實際上沒有使用GCD事件源與(我已經使用過其他類型的GCD源代碼),所以我不確定是否對事件點擊創建的端口有一些限制。您是否嘗試了CFRunLoop的處事方式,只是爲了確保至少水龍頭正確地創建並在這種情況下工作? – 2010-07-21 19:49:36

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