2012-10-10 115 views
1

我面對關於發送/馬赫通過端口接收消息一個奇怪的延遲問題。 我的實現的基本概念如下:CFMessagePort古怪

插件創建本地端口→啓動遠程進程,它發送一個 消息發送到所述端口→返回接收的數據。

這裏是插件部分:

static NSArray *returned=nil; 
static CFDataRef handle_port (
    CFMessagePortRef local, 
    SInt32 msgid, 
    CFDataRef d, 
    void *info 
) { 
    NSPropertyListFormat format; 
    NSDictionary* ret = [NSPropertyListSerialization propertyListWithData:(NSData*)d 
              options: NSPropertyListImmutable 
              format: &format 
              error: nil]; 
    returned=[NSArray arrayWithArray:[ret objectForKey:@"aKey"]]; //this is what I want returned from the portRet() 
    NSLog(@"returned array %@",returned); 
    return NULL;  
} 

NSArray* portRet(){ 
    CFMessagePortRef port = CFMessagePortCreateLocal(kCFAllocatorDefault, CFSTR("com.someport"), handle_port, NULL, NULL); 
    CFRunLoopSourceRef source = CFMessagePortCreateRunLoopSource(kCFAllocatorDefault, port, 0); 
    CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes); 
    CFRelease(source); 
    int r=system("/path/someExecutable"); 
    if(r !=0) NSLog(@"Program error"); 
    //CFMessagePortInvalidate(port);  
    //CFRelease(port); 
    return returned; // always returns nil 
} 

和someExecutable代碼的重要組成部分如下:

int main(){ 
... 
CFMessagePortRef port = CFMessagePortCreateRemote(NULL, CFSTR("com.someport")); 
    if(port == NULL) exit(1); 
    CFDataRef d=CFPropertyListCreateData(kCFAllocatorDefault,[NSDictionary dictionaryWithObject:anArray forKey:@"aKey"], kCFPropertyListXMLFormat_v1_0, 0, NULL); 
    CFMessagePortSendRequest (port, 0, d, 0, 0, NULL, NULL); 
    NSLog(@"Program is about to exit"); 
    CFRelease(d); 
... 
    exit(0); 
} 

是正常發送來自遠程過程的消息,但在回調被稱爲後的過程已經結束,portRet()返回空值。 如果我使portRet()函數中的端口無效,則不會收到該消息。

我想不通爲什麼這種延遲發生的原因。我想要實現的是在返回portRet()之前調用端口回調函數。我也曾嘗試使用主調度隊列,而不是一個CFRunLoopSource爲港口的回調調度:

CFMessagePortSetDispatchQueue(port, dispatch_get_main_queue()); 

但結果卻是大同小異的。我不確定我做錯了什麼。 我們非常感謝您的幫助。

回答

0

您需要在portRet運行運行循環,直到第二個過程返回一個值。例如:

SInt32 runLoopRunReturnValue = CFRunLoopRunInMode(kCFRunLoopDefaultMode, CFDateGetTimeIntervalSinceDate((__bridge CFDateRef)[NSDate distantFuture], (__bridge CFDateRef)[NSDate date]), true); 

if (runLoopRunReturnValue == kCFRunLoopRunHandledSource) 
    return returned; 
else { 
    // Throw exception or whatever 
    // (although this will never be called using the above implementation 
    // since [NSDate distantFuture] is wayy into the future...) 
}