2015-03-13 61 views
0

在我的代碼中,我想單獨處理隊列中的操作,並且能夠暫停和恢復隊列中的操作操作。我怎樣才能實現呢?在單個NSOperationQueue中管理多個操作像暫停/恢復單一操作

讓我簡單解釋一下我的問題,我用下面的代碼來創建子類NSOperation的操作,並將此操作添加到NSOperationQueue中。

@interface MyLengthyOperation: NSOperation 
@end 

@implementation MyLengthyOperation 
- (void)main 
{ 
    // a lengthy operation 
    @autoreleasepool 
    { 
     for (int i = 0 ; i < 10000 ; i++) 
     { 

      // is this operation cancelled? 
      if (self.isCancelled) 
      break; 

      NSLog(@"%f", sqrt(i)); 
     } 
    } 
} 
@end 

我上面操作中創建和我與

NSOperationQueue *myQueue = [[NSOperationQueue alloc] init]; 
myQueue.name = @"Download Queue"; 
myQueue.maxConcurrentOperationCount = 4; 
[myQueue addOperation:operation]; 

稱它現在我想暫停和恢復我的操作。讓我們假設循環是在6786上,然後按下暫停按鈕,然後隊列應該暫停這個操作,當我按下開始時,它應該從6786開始。

我想控制隊列中的多個操作。我怎樣才能做到這一點 ?

我看着[queue setSuspended:YES]; - 這將阻止隊列添加新的操作,但我想控制隊列中的現有操作。

等待您的答案。

在此先感謝!

回答

6

如果你想要這個行爲,那麼你需要自己構建它,而沒有內建的能夠暫停某個NSOperation的能力。

您可以使用NSCondition做到這一點 -

@interface MyLengthyOperation: NSOperation 

@property (atomic) BOOL paused; 
@property (nonatomic,strong) NSCondition *pauseCondition; 

@end 

@implementation MyLengthyOperation 

-(instancetype) init { 
    if (self=[super init]) { 
     self.pauseCondition=[NSCondition new]; 
    } 
    return self; 
} 

- (void)main 
{ 
    // a lengthy operation 
    @autoreleasepool 
    { 
     for (int i = 0 ; i < 10000 ; i++) 
     { 

      // is this operation cancelled? 
      if (self.isCancelled) 
      break; 

      [self.pauseCondition lock]; 
      while (self.paused) { 
       [self.pauseCondition wait]; 
      } 
      NSLog(@"%f", sqrt(i)); 
      [self.pauseCondition unlock]; 
     } 
    } 
} 

-(void)pause { 
    [self.pauseCondition lock]; 
    self.paused=YES; 
    [self.pauseCondition signal]; 
    [self.pauseCondition unlock]; 
} 

-(void)resume { 
    [self.pauseCondition lock]; 
    self.paused=NO; 
    [self.pauseCondition signal]; 
    [self.pauseCondition unlock]; 
} 
777441end 

然後你可以說[myOperation pause][myOperation resume]

+2

檢查你的答案後,我認爲這應該做一個竅門,我一定會嘗試上面的代碼,希望它會解決我的問題,並非常感謝你@ Paulw11快速和詳細的答案。真的很欣賞它! – 2015-03-15 00:50:44

4

NSOperation不提供暫停操作開箱支持,你將不得不實施你自己。一個策略是使用條件變量(請參閱Paulw11的答案)。您甚至可以使用單個條件變量同時控制多個操作。

但是,如果你想暫停許多併發操作,這種方法可能會有問題。每個暫停的操作都會阻塞一個線程。使用條件變量確保那些被阻塞的線程不使用任何CPU,但是這些線程的內存不能被重用。根據暫停線程的數量以及您在此期間想要執行的操作,此內存使用情況可能會有問題。蘋果公司將此列爲應避免的事情。

另一種方法是「拆分」操作。所以,當你想暫停你首先掛起隊列,然後讓每個操作排隊一個新的操作對象,該對象從停止的地方開始。這當然需要更多的參與改變。

在你的例子中,你會給你的操作子類一個屬性firstNumber,並開始你的循環,而不是在零。然後暫停時,您將創建一個新的操作,將當前循環索引作爲firstNumber並將其排入隊列。

這不僅爲您提供了在隊列暫停時不阻塞任何線程的優勢。而且有了這種可能性,您可以實現一個持久隊列,將掛起的操作保存到磁盤,並在下一次應用程序啓動時恢復它們。