0

我正在为 Mac 上的 Adob​​e Premiere 编写一个插件,它打开一个外部应用程序,然后使用 NSPipe 和 NSFileHandle 从外部应用程序读取标准输出。我知道这样做的推荐方法包括使用 NSNotificationCenter 以及 NSFileHandle 的 read​In​Background​And​Notify 命令,或者使用 NSFilehandle 的 setReadabilityHandler 方法在输出到达时一次读取一行:

NSTask appTask... // my task which is launching the external app
NSPipe* myPipe = [[NSPipe alloc] init];
[appTask setStandardOutput:[myPipe fileHandleForReading]];
[[myPipe fileHandleForWriting] setReadabilityHandler:^(NSFileHandle *file) {
    NSData* dataRead = [file availableData];
    if (dataRead != nil) {
        printf("Read a line\n");
    }
}];

当我从 Xcode 启动带有调试器的 Premiere 时,这工作得很好。但是,当我自己运行 Premiere 时,当外部应用程序在其标准输出中放入一行时,不会调用块(或通知,如果我使用该方法)。我假设有一些奇怪的方式,当它通过 Xcode 运行时,它运行的线程有一个运行循环,当插件从 Premiere 启动时它以某种方式不活动运行。

我可以解决这个问题的一种方法是只有一个循环,每秒检查几次是否有东西要从在后台线程中运行的管道的 NSFileHandle 中读取。但是,我找不到任何方法来检查是否有东西可以从 NSFileHandle 读取,而无需阻塞,直到有东西准备好(即使有东西准备好,当没有通过 Xcode 启动时,阻塞也会由于某种原因保持阻塞)。

所以我希望有两种解决方案之一:1)通过某种方法来纠正 NSRunLoop 的任何问题,即当管道的 NSFileHandle 中有东西准备好时,通知/回调块不会被触发。或 2) 某种方法来检查管道的 NSFileHandle 中是否有准备好读取的内容,而不会阻塞,直到准备好读取某些内容。

谢谢你的帮助!!!!

4

1 回答 1

1

好吧,看起来实际的问题是,当从 Xcode 中启动所有内容时,当我打印到 stdout 时,我的外部应用程序会立即刷新 stdout 缓冲区,但是在没有 Xcode 的情况下启动东西时,我需要添加以下行来手动刷新它:

fflush(标准输出);

所以问题出在这个问题上,而不是我的插件中的代码没有正确地等待和从管道中读取!

于 2017-04-04T18:33:01.010 回答