2016-04-27 26 views
0

我尝试使用分布式对象在其他进程中显示窗口。 进程A通过显示对话框的进程B的分布式对象方法远程调用。如果我试图等待结果,会发生错误。 该方法看起来像这样:ObjectiveC - 通过分布式对象显示窗口

-(BOOL)showWindow //method invoked through distributed objects 
{  
    dispatch_semaphore_t sem = dispatch_semaphore_create(0); 
    [object showDialog:^(BOOL result){ //this methods creates and display window 
     NSLog(@"Block called"); 
     dispatch_semaphor_signal(sem); 
    }]; 
    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); 
    return YES; 
} 

功能的ShowWindow永远不会结束。如果我评论dispatch_semaphore_wait显示“Block called”并显示窗口。 我检查了不同的变体同步,我尝试使用dispatch_sync或异步运行此代码,但没有任何帮助。

我会帮助你的。 Kon

回答

0

问题是,DO要求运行循环运行以处理双方之间的通信。基本上,您显示的代码会向远程端发送请求,远程端会承载object所代表的实际对象。该请求携带对本地块对象的引用。远程端有效地得到了一个代理。

一段时间后,远程端调用其代理块。这会导致请求被发送回该进程和线程。但是,此线程无法接收该请求,因为它在dispatch_semaphore_wait()中被阻止。它不参与任何沟通渠道。

所以,双方都陷入僵局。本地方永远等待永远不会发出信号的信号量,并且远程方等待其运行该块完成的请求。

想想另一种方式,信号量是而不是通过远程进程发送信号。你已经要求它通过正在等待的同一个线程发出信号。只是,如果可能的话,这个线程会响应另一个进程发送的事件。让一个线程负责发送它所等待的信号量是一个非常明显,直接的自我死锁。

你可以更改-showWindow不同步吗?为什么它使用信号灯并等待?为什么它不能仅仅触发请求,然后返回到调用代码,它不应该假定对话已完成,而是一直返回到主事件循环?无论发生什么工作,“下一个”应该放入完成块中,并且只在对话完成时才被异步调用。

如果你真的需要这种方法是同步的,那么你将不得不使用运行循环来等待调度信号量。喜欢的东西:

-(BOOL)showWindow //method invoked through distributed objects 
{  
    __block BOOL done = NO; 
    [object showDialog:^(BOOL result){ //this methods creates and display window 
     NSLog(@"Block called"); 
     done = YES; 
    }]; 
    NSString* mode = @"com.yourcompany.yourapp.privatemode"; 
    NSConnection* conn = [(NSDistantObject*)object connectionForProxy]; 
    [conn addRequestMode:mode]; 
    while (!done) 
     [[NSRunLoop currentRunLoop] runMode:mode beforeDate:[NSDate distantFuture]]; 
    [conn removeRequestMode:mode]; 
    return YES; 
} 

也许,你实际上应该将私人模式添加到连接它的第一次创建的时候,让它在那里其寿命。您不希望为此使用任何预定义的模式,因为当您在等待并且您的代码意外地重新进入等时,意外的事情可能会触发。等等。