2016-04-27 56 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; 
} 

也許,你實際上應該將私人模式添加到連接它的第一次創建的時候,讓它在那裏其壽命。您不希望爲此使用任何預定義的模式,因爲當您在等待並且您的代碼意外地重新進入等時,意外的事情可能會觸發。等等。