2012-12-04 60 views
1

我有一個Swing應用程序,並進行JNI方法調用,打開NSOpenPanel。在一些電腦上(我不知道它們之間有什麼相似之處),它完全掛起了應用程序。在大多數電腦上它的工作正常。如果代碼將應用程序掛在特定的Mac上,則每次執行時都會執行該代碼。NSOpenPanel掛起java應用程序

這裏是我如何開一個NSOpenPanel:

JNF_COCOA_ENTER(env);  
// My helper Obj-c object to make a selector call 
OpenFileObject *openFile = [[OpenFileObject alloc] init];  
if ([NSThread isMainThread]) 
    [openFile showOpenFileDialog]; 
else 
    [JNFRunLoop performOnMainThread:@selector(showOpenFileDialog) on:openFile withObject:nullptr waitUntilDone:TRUE]; 
// ...Handles results  
JNF_COCOA_EXIT(env); 

這裏是showOpenFileDialog方法:

NSOpenPanel *panel = [NSOpenPanel openPanel]; 
[panel setCanChooseFiles:canChooseFiles]; 
[panel setCanChooseDirectories:canChooseFolders]; 
[panel setAllowsMultipleSelection:allowMultiSelection]; 
[panel setAllowedFileTypes:fileTypes]; 
[panel setTitle:dialogTitle]; 

if ([panel runModal] == NSFileHandlingPanelOKButton) 
    urls = [[panel URLs] copy]; 
else 
    urls = nullptr; 

,這裏是掛起報告:https://gist.github.com/4207956

任何想法?

回答

1

首先,我懷疑這有什麼關係你的問題,但我會謹慎使用nullptrTRUE的作爲參數傳遞給performOnMainThread:...相反,我會做:

[JNFRunLoop performOnMainThread:@selector(showOpenFileDialog) on:openFile withObject:nil waitUntilDone:YES];

只要是在安全的一面。

從堆棧跟蹤中,假設這是一個大堆棧,並且您將它分開以添加有關您的幫助對象方法調用的註釋,似乎正在採用的代碼路徑是[NSThread isMainThread]返回NO的代碼路徑。這意味着它在後臺線程上(__NSThreadPerformPerform然後執行JNFRunLoop的出價)。

堆棧永遠不會從NSOpenPanel的初始化路徑中跳出,並以某種方式深入底層,它再次訪問運行循環的東西。在我看來,似乎發生了某種僵局。

如果JNFRunLoop在另一個線程等待的showOpenFileDialog方法的執行來完成對主運行循環,並在東西是openPanel試圖等待在同一運行循環的事情,這可能導致死鎖。

我不熟悉Java和Cocoa之間的集成,但可能有一些方法可以避免在非主線程上執行第一個代碼片段?

或者,你可以嘗試使用:

[openFile performSelectorOnMainThread:@selector(showOpenFileDialog) withObject:nil waitUntilDone:YES];

在非主線程路徑

+0

可能是不相關的,但由於緩衝區溢出,我確實在類似的堆棧中發現了這樣的崩潰:http://www.cocoabuilder.com/archive/cocoa/130423-nssavepanel-crashing-on-instantiation.html – lyricsboy