6

使用一些代碼,我遇到了運行循環,這是我新來的,在NSOperation的內部。在NSOperation中使用NSThread睡眠

NSOperation正在忙於下載數據 - 雖然他們很忙,但有代碼等待下載完成,並以NSRunLoop和線程休眠的形式完成。

此代碼特別感興趣的是我:

while (aCertainConditionIsTrue && [self isCancelled]==NO) { 
    if(![[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1.0]]){ 
     [NSThread sleepForTimeInterval:1.0]; 
    } 
} 

我讀過有關運行循環和runMode:beforeDate:將等待輸入源或超時。雖然我不是100%作爲輸入源。

在第一次執行此操作時,它始終返回NO並點擊sleepForTimeInterval:。這不好嗎?

在特定的實用程序類中,它很多次碰到sleepForTimeInterval: - 每個線程一次 - 顯着傷害了性能。

任何更好的解決方案,或建議?

回答

2

睡眠鎖定線程。也許你改變你的代碼來使用performSelector:withObject:afterDelay。這樣你的線程可以繼續運行。

... 
    done = NO; 
    [self checkDoneCondition:nil]; 
    ... 

- (void)checkDoneCondition:(id)object { 
    if (aCertainConditionIsTrue && [self isCancelled]==NO) { 
     if(...) { 
      [self performSelector:@selector(checkDoneCondition:) withObject:[con error] afterDelay:1.0]; 
     } else { 
      done = YES; 
     } 
    } 
} 
1

看起來你需要使用併發的NSOperation。這是在蘋果文檔的相關部分:

相較於非併發操作,它運行同步,一個 併發操作異步運行。換句話說,當您調用併發操作的開始方法時,該方法可能在相應的任務完成之前返回 。這可能發生在 之中,因爲操作對象創建了一個新線程來執行任務 或因爲該操作稱爲異步功能。當控制返回到 調用者時,如果操作正在進行,它並不是 ,而只是它可能正在進行。 (...) 在併發操作中,您的啓動方法負責 以異步方式啓動操作。無論您是生成一個 線程還是調用異步函數,都可以使用此方法。 開始操作時,您的啓動方法還應更新isExecuting 方法所報告的操作的執行狀態 。您可以通過發送KVO通知來執行 isExecuting關鍵路徑,從而讓感興趣的客戶知道 操作正在運行。您的isExecuting方法還必須以線程安全的方式返回 狀態。

(從https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html

換句話說,你可以在你的NSOperation子類中重寫-start方法,並具有爲executingfinished財產伊娃。此方法將在單獨的線程中開始下載。下載開始時,您將設置executing標誌並觸發KVO。當它在這個線程中完成時,您可以使用finishedexecuting。看起來很複雜,但實際上很簡單。

另請參見Stack Overflow上的這個問題,其中有一個很好的解釋:Subclassing NSOperation to be concurrent and cancellable