簡體   English   中英

NSOperationQueue在完成塊成功時添加新操作

[英]NSOperationQueue add new operation when completion block is successful

我試圖在后台線程上以串行順序完成一些操作。

我正在調用的函數已經有一個完成塊,所以當函數完成時,我想用一個新的參數調用相同的函數。

所以基本上是連續的操作。

dispatch_asyncDISPATCH_QUEUE_SERIAL ,以正確的順序觸發函數,但是在調用下一個函數之前並不關心第一個函數是否已完成,因此我不想使用它們。

NSOperationQueue* serialQ = [[NSOperationQueue alloc] init]; serialQ.maxConcurrentOperationCount = 1; 對我來說更有意義。 因此,當第一個函數開始計算隊列中的第二個函數時,必須等待它完成其完成塊。

NSOperationQueue* serialQ = [[NSOperationQueue alloc] init];
    serialQ.maxConcurrentOperationCount = 1; //this will set this queue to Serial



        for (File *file in queueArrray) {
            Streamer *streamer=[[Streamer alloc] init];

            NSBlockOperation *downloadOperation = [[NSBlockOperation alloc] init];

            __weak NSBlockOperation *weakDownloadOperation = downloadOperation;

            [weakDownloadOperation addExecutionBlock:^{
                [streamer loadFile:file withCallback:^(NSString *error, BOOL success) {
                    if (success) {
                        NSLog(@"file loaded %@",file.fileUrl);
                        //here start the next operation !!!!!!!!
                        ??????????????????????????????????????
                    }
                }];
            }];  
        }

串行隊列實際情況可確保添加到隊列中要執行的第一個塊在第二個塊執行之前已完成。

-(void)testSerialQueue
{
    dispatch_queue_t serialQueue = dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL);

    dispatch_async(serialQueue, ^{
        [self countTo100];
    });

    dispatch_async(serialQueue, ^{
        [self countFrom200To400];
    });

    dispatch_async(serialQueue, ^{
        [self countFrom400To500];
    });

}

- (void)countTo100
{
    for (int i = 0; i < 100; i++) {
        NSLog(@"%d", i);
    }
}

- (void)countFrom200To400
{
    for (int i = 200; i < 400; i++) {
        NSLog(@"%d", i);
    }
}

- (void)countFrom400To500
{
    for (int i = 400; i < 500; i++) {
        NSLog(@"%d", i);
    }
}

如果您從上方查看日志,它將先從0 .. 100開始打印,然后從200 .. 400和400 .. 500開始打印。

現在,考慮以下代碼片段,在其中您可以在並發塊中執行每個方法,例如:

-(void)testSerialQueue
{
    dispatch_queue_t serialQueue = dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL);

    dispatch_async(serialQueue, ^{
        [self countTo100];
    });

    dispatch_async(serialQueue, ^{
        [self countFrom200To400];
    });

    dispatch_async(serialQueue, ^{
        [self countFrom400To500];
    });

}

- (void)countTo100
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(concurrentQueue, ^{
        for (int i = 0; i < 100; i++) {
            NSLog(@"%d", i);
        }
    });

}

- (void)countFrom200To400
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(concurrentQueue, ^{
        for (int i = 200; i < 400; i++) {
            NSLog(@"%d", i);
        }
    });
}

- (void)countFrom400To500
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(concurrentQueue, ^{
        for (int i = 400; i < 500; i++) {
            NSLog(@"%d", i);
        }
    });
}

在這里,您在串行隊列中添加了所有方法,但是方法本身在並發塊中運行。 因此,在這種情況下,結果是隨機的。 您也可以像這樣使用dispatch_group序列化它,

-(void)testSerialQueue
{
    dispatch_queue_t serialQueue = dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL);

    self.group = dispatch_group_create();

    dispatch_async(serialQueue, ^{
        [self countTo100];
    });

    dispatch_async(serialQueue, ^{
        [self countFrom200To400];

    });

    dispatch_async(serialQueue, ^{
        [self countFrom400To500];
    });
}

- (void)countTo100
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_enter(self.group);

    dispatch_async(concurrentQueue, ^{
        for (int i = 0; i < 100; i++) {
            NSLog(@"%d", i);
        }
        dispatch_group_leave(self.group);
    });
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}

- (void)countFrom200To400
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_enter(self.group);

    dispatch_async(concurrentQueue, ^{
        for (int i = 200; i < 400; i++) {
            NSLog(@"%d", i);
        }
        dispatch_group_leave(self.group);
    });
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);

}

- (void)countFrom400To500
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_enter(self.group);

    dispatch_async(concurrentQueue, ^{
        for (int i = 400; i < 500; i++) {
            NSLog(@"%d", i);
        }
        dispatch_group_leave(self.group);

    });
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);

}

在這里,您將再次看到它按順序打印日志。 因此,dispatch_group用於序列化並發操作。 您可能希望此時刪除serialQueue中的dispatch_async。

現在,操作隊列讓我們看一個簡單的例子,

-(void)testSerialQueue
{
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 1;

    NSBlockOperation *operation1 = [[NSBlockOperation alloc] init];
    NSBlockOperation *operation2 = [[NSBlockOperation alloc] init];
    NSBlockOperation *operation3 = [[NSBlockOperation alloc] init];

    [operation1 addExecutionBlock:^{
        [self countTo100];
    }];

    [operation2 addExecutionBlock:^{
        [self countFrom200To400];
    }];

    [operation3 addExecutionBlock:^{
        [self countFrom400To500];
    }];        
}

- (void)countTo100
{
    for (int i = 0; i < 100; i++) {
        NSLog(@"%d", i);
    }
}

- (void)countFrom200To400
{
    for (int i = 200; i < 400; i++) {
        NSLog(@"%d", i);
    }
}

- (void)countFrom400To500
{
    for (int i = 400; i < 500; i++) {
        NSLog(@"%d", i);
    }
}

將count方法添加到NSOperationQueue中,並將maxConcurrentOperation設置為'1',這現在更像是串行隊列。 每種方法都不會產生其他一些隊列,因此,計數是在同一串行隊列上執行的。 因此,它們都按順序打印。

現在,讓我們看一個模擬您的案例的示例。

-(void)testSerialQueue
{
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 1;

    NSBlockOperation *operation1 = [[NSBlockOperation alloc] init];
    NSBlockOperation *operation2 = [[NSBlockOperation alloc] init];
    NSBlockOperation *operation3 = [[NSBlockOperation alloc] init];

    [operation1 addExecutionBlock:^{
        [self countTo100];
    }];

    [operation2 addExecutionBlock:^{
        [self countFrom200To400];
    }];

    [operation3 addExecutionBlock:^{
        [self countFrom400To500];
    }];        
}

- (void)countTo100
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(concurrentQueue, ^{
        for (int i = 0; i < 100; i++) {
            NSLog(@"%d", i);
        }
    });

}

- (void)countFrom200To400
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(concurrentQueue, ^{
        for (int i = 200; i < 400; i++) {
            NSLog(@"%d", i);
        }
    });
}

- (void)countFrom400To500
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(concurrentQueue, ^{
        for (int i = 400; i < 500; i++) {
            NSLog(@"%d", i);
        }
    });
}

在這種用例中,您將操作添加到NSOperationQueue(即串行隊列)中,但是同樣,各個方法在其他一些並發隊列中運行。 因此,執行順序是相當隨機的。 現在,您可以像前面處理串行隊列一樣使用dispatch_group解決此問題。

-(void)testSerialQueue
{
    self.group = dispatch_group_create();

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 1;

    NSBlockOperation *operation1 = [[NSBlockOperation alloc] init];
    NSBlockOperation *operation2 = [[NSBlockOperation alloc] init];
    NSBlockOperation *operation3 = [[NSBlockOperation alloc] init];

    [operation1 addExecutionBlock:^{
        [self countTo100];
    }];

    [operation2 addExecutionBlock:^{
        [self countFrom200To400];
    }];

    [operation3 addExecutionBlock:^{
        [self countFrom400To500];
    }];        
}

- (void)countTo100
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_enter(self.group);

    dispatch_async(concurrentQueue, ^{
        for (int i = 0; i < 100; i++) {
            NSLog(@"%d", i);
        }
        dispatch_group_leave(self.group);
    });
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}

- (void)countFrom200To400
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_enter(self.group);

    dispatch_async(concurrentQueue, ^{
        for (int i = 200; i < 400; i++) {
            NSLog(@"%d", i);
        }
        dispatch_group_leave(self.group);
    });
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);

}

- (void)countFrom400To500
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_enter(self.group);

    dispatch_async(concurrentQueue, ^{
        for (int i = 400; i < 500; i++) {
            NSLog(@"%d", i);
        }
        dispatch_group_leave(self.group);

    });
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);

}

現在,您將看到計數再次有序。 這是因為dispatch_group一直等待直到每個異步任務完成。

對於您的特定用例,您可以使用循環調用某些方法,像這樣創建NSInvocationOperation,

-(void)testSerialQueue
{
    self.group = dispatch_group_create();

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 1;


    NSArray *selectors = @[@"countTo100", @"countFrom200To400", @"countFrom400To500"];

    for (NSString *selector in selectors) {
        NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
                                                                                selector:NSSelectorFromString(selector)
                                                                                  object:nil];
        [queue addOperation:operation];
    }

}

- (void)countTo100
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_enter(self.group);

    dispatch_async(concurrentQueue, ^{
        for (int i = 0; i < 100; i++) {
            NSLog(@"%d", i);
        }
        dispatch_group_leave(self.group);
    });
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}

- (void)countFrom200To400
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_enter(self.group);

    dispatch_async(concurrentQueue, ^{
        for (int i = 200; i < 400; i++) {
            NSLog(@"%d", i);
        }
        dispatch_group_leave(self.group);
    });
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);

}

- (void)countFrom400To500
{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_enter(self.group);

    dispatch_async(concurrentQueue, ^{
        for (int i = 400; i < 500; i++) {
            NSLog(@"%d", i);
        }
        dispatch_group_leave(self.group);

    });
    dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);

}

您的目標方法是異步的。 這意味着您不能使用普通的塊操作,您需要創建一個自定義操作子類,以便在異步方法完成之前該操作不會完成。

在google中搜索創建異步操作子類的示例,因為您需要整理一些東西。

或者,您可能會有一些文件數組(或其他內容)之類的東西,並且每當您的異步方法完成之后,檢查那里是否有任何東西,請刪除第一項並進行處理。 這將一直進行到數組為空為止。

您可以使用信號量等待功能完成,如果成功,則使用參數再次調用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM