【问题标题】:Can't Find Cocoa GUI Thread in C++ Application w/ Objective-C++ GUI在带有 Objective-C++ GUI 的 C++ 应用程序中找不到 Cocoa GUI 线程
【发布时间】:2010-12-07 23:17:14
【问题描述】:

我有一个没有 GUI 的多 posix 线程 Linux C++ 应用程序,我希望能够在其中偶尔使用 Cocoa 控件,即文件上传/下载对话框和警报。

我远非 Cocoa 专家,但能够构建一些按预期工作的 Objective-C++ 测试/演示应用程序。

现在我已将 Cocoa 代码集成到我的应用程序中,我似乎无法将内容发布到主 GUI 线程。也许我没有做我需要做的事情来创建一个,我真的不确定。这是我的 .mm 文件中的内容:

#ifdef MACOS
@interface CocoaInterface : NSObject
{
}
- (id) init;
- (void) ShowFileUploadDialog;
- (void) ShowFileDownloadDialog;
@end

@implementation CocoaInterface
- (id) init
{
    cout << "Creating NSAutoreleasePool" << endl;
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    cout << "Creating NSApplication" << endl;
    NSApplication* app = [[NSApplication alloc] init];
    cout << "Calling NSApplication::finishLaunching" << endl;
    [app finishLaunching];
    [super init];
    return self;
}

- (void) ShowFileUploadDialog
{
    cout << "Entering ShowFileUploadDialog" << endl;
    if ([NSThread isMainThread])
    {
        // Show file dialog
        cout << "Calling NSRunAlertPanel" << endl;
        NSRunAlertPanel(@"This is a test", @"Does it work?", @"Yes", @"No", @"");
    }
    else 
    {
        //NSRunAlertPanel(@"This is a test", @"Does it work?", @"Yes", @"No", @"");
        cout << "Redirecting ShowFileUploadDialog call to main thread." << endl;
        [self performSelectorOnMainThread:@selector(ShowFileUploadDialog) withObject:nil waitUntilDone:YES];
    }
}

- (void) ShowFileDownloadDialog
{
    cout << "Entering ShowFileDownloadDialog" << endl;
    if ([NSThread isMainThread])
    {
        // Show file dialog
        cout << "Calling NSRunAlertPanel" << endl;
        NSRunAlertPanel(@"This is a test", @"Does it work?", @"Yes", @"No", @"");
    }
    else
    {
        //NSRunAlertPanel(@"This is a test", @"Does it work?", @"Yes", @"No", @"");
        cout << "Redirecting ShowFileDownloadDialog call to main thread." << endl;
        [self performSelectorOnMainThread:@selector(ShowFileDownloadDialog) withObject:nil waitUntilDone:YES];
    }
}
@end 
#endif

我从处理传入网络消息的各个线程中的代码中调用它:

cout << "Creating CocoaInterface." << endl;
CocoaInterface* interface = [[CocoaInterface alloc] init];
cout << "Calling CocoaInterface::ShowFileDownloadDialog." << endl;
[interface ShowFileDownloadDialog];

这会在尝试执行选择器时挂起——好像它永远无法真正找到主线程。 GDB 中的回溯显示我一直在等待信号量。

当我在 performSelectorOnMainThread 调用之前取消注释 NSRunAlertPanel 调用时,我得到一个对话框形状的白色块,但它没有完全绘制或处理任何消息,可能是因为它不在主 GUI 线程上。

似乎我没有合适的 GUI 线程,或者无法从我所在的位置访问它。我怀疑我在初始化中遗漏了一些东西。有什么建议吗?

【问题讨论】:

    标签: multithreading cocoa user-interface macos objective-c++


    【解决方案1】:

    您应该调用 NSApplicationLoad() 来处理实例化并为您创建事件循环,而不是显式创建 NSApplication 对象。

    如果需要,您还可以使用 NSLog(@"Some string") 函数来代替所有 couts。

    【讨论】:

    • 谢谢,但似乎 NSApplicationLoad() 是为 Carbon 应用程序设计的,并且在这个特定的应用程序中没有 Carbon。
    【解决方案2】:

    事实证明,我需要的是这两件事的结合:

    [NSApplication sharedApplication];
    [NSApp run];
    

    我已经被 GTK 和 wxWidgets 等其他 GUI API 宠坏了,所以调用

    [NSApp terminate: nil];
    

    通过 exit(0) 调用意外地破坏了整个应用程序,让我措手不及,而 main() 的其余部分从未执行,但这显然是预期的行为和另一天的主题。

    【讨论】:

    • 是的,这是预期的行为。它写在文档的某处。
    猜你喜欢
    • 2015-12-30
    • 1970-01-01
    • 2011-12-10
    • 1970-01-01
    • 1970-01-01
    • 2010-09-25
    • 1970-01-01
    • 2022-07-01
    • 2011-08-27
    相关资源
    最近更新 更多