2

私は現在、GraphicsMagick の助けを借りて、多くの画像を次々に処理するシェル スクリプトを持っています。それは正常に機能し、すべての計算が正しく、すべてが機能します。(これは「単純な」スクリプトではありません。JSON ファイルから寸法を読み取り、多くの制約に関して一連の画像を変換する必要があります)。

デュアルコアまたはクアッドコアのコンピューターで作業しているため、並列化したいと考えています。また、私は iPhone 開発者であり、Mac 開発について自己紹介するのが好きなので、「コマンドライン ツール」テンプレートを使用して、XCode と Objective-C で作成したいと考えています。

ここまでは順調ですが、「タスク ディスパッチャ」オブジェクトの設計に直面しています。GCDの有無にかかわらず、ARCの有無にかかわらず、ブロックを使用して、実行ループ、個別のスレッドでNSTaskを実行する間でかなり迷っています。

どうすればこれを達成できますか?単純なスレッドを使用して NSTask を生成し、完了時に報告させ、ディスパッチャーのデリゲートに通知して進行状況バーをアップグレードできるようにすることを考えていました。でもどうしてもGrand Central Dispatchに連絡したいんです。何をすべきか、何をすべきでないかについて、考え、アイデア、アドバイスを持っている人はいますか?

編集: Apple のドキュメントを読んでいて、NSOperationQueue クラスを見つけました。これはまさに私がここで必要としているものでしょうか?

4

3 に答える 3

4

パラメータや環境変数を含む独立したプロセスを起動するために使用するのに適したクラスはNSTaskです。厄介な詳細については、ドキュメントを参照してください。これは、10個の並行プロセスを開始し、それらが終了するのを待つ小さなコマンドラインツールです。タスクはすでに同時に起動されているため、NSOperationQueueはここでは冗長になります。

-編集:同時実行が制限された改良バージョン-

int main (int argc, const char * argv[])
{
   @autoreleasepool {

       // Let's not have more than 5 parallel processes
       dispatch_semaphore_t limit = dispatch_semaphore_create(5);
       dispatch_semaphore_t done  = dispatch_semaphore_create(0);

       for (int i=0;  i<10;  i++) {
           // Setup the taks as you see fit including the environment variables.
           // See docs on NSTask for more on how to use this object.
           NSTask *task = [[NSTask alloc] init];
           task.launchPath = @"/bin/ls";
           task.arguments = [NSArray arrayWithObject:@"-la"];
           task.terminationHandler = ^(NSTask *task) {
               dispatch_semaphore_signal(limit);
               if (i==9) dispatch_semaphore_signal(done);
           };

           dispatch_semaphore_wait(limit, DISPATCH_TIME_FOREVER);
           [task launch];
       }
       dispatch_semaphore_wait(done, DISPATCH_TIME_FOREVER);
       dispatch_release(limit);
       dispatch_release(done);
   }
   return 0;

}

- 元のバージョン -

int main (int argc, const char * argv[])
{
    @autoreleasepool {

        NSObject *lock = [[NSObject alloc] init];
        int __block counter = 10;

        for (int i=0;  i<10;  i++) {
            // Setup the taks as you see fit including the environment variables.
            // See docs on NSTask for more on how to use this object.
            NSTask *task = [[NSTask alloc] init];
            task.launchPath = @"/bin/ls";
            task.arguments = [NSArray arrayWithObject:@"-la"];
            task.terminationHandler = ^(NSTask *task) {
                @synchronized(lock) { counter--; }
            };
            [task launch];
        }

        while (counter)
            usleep(50);

        [lock release];
    }
    return 0;
}

あなたの場合、管理を容易にするためにNSTaskオブジェクトを配列に保持したい場合があります。

于 2011-09-06T18:31:38.893 に答える
1

はい - NSOperation/NSOperationQueueこのタスクに適しています。

私は次のようなものから始めます:

@protocol MONTaskRequestDelegate

- (void)taskRequestDidComplete:(MONTaskRequest *)taskRequest;

@end

@interface MONTaskRequest : NSOperation
{
@private
    NSTask * task;
    NSObject<MONTaskRequestDelegate>* delegate; /* strong reference. cleared on cancellation and completion, */
}

- (id)initWithTask:(NSTask *)task delegate:(NSObject<MONTaskRequestDelegate>*)delegate;

// interface to access the data from the task you are interested in, whether the task completed, etc.

@end

@implementation MONTaskRequest

// ...

- (void)performDelegateCallback
{
    [self.delegate taskRequestDidComplete:self];
    self.delegate = nil;
}

- (void)main
{
    NSAutoreleasePool * pool = [NSAutoreleasePool new];

    [self runTheTask];
    // grab what is needed and handle errors
    [self performDelegateCallback];

    [pool release];
}

- (void)cancel
{
    [super cancel];
    [self stopTaskIfPossible];
    [self performDelegateCallback];
}

@end

NSOperationQueue次に、アクティブなタスクの数を妥当な数に制限するために使用できます。

于 2011-09-06T19:15:23.170 に答える
-1

この目的のために、[myObj performSelectorInBackground:@selector(doSomething) withObject:nil]; を使用します。NSObject の機能。

アイデアは非常に単純です。作業を行うメソッドを作成し、前述のメソッドを使用してメイン スレッドから呼び出します。次に、別のスレッドからの結果を何らかの方法で処理する必要がある場合は、コールバック セレクターを呼び出します。

于 2011-09-06T11:36:45.790 に答える