是否可以通過將maxConcurrentOperationCount
設置爲1來將NSoperationQueue
對象用作串行FIFO隊列?NSOperationQueue串行FIFO隊列
我注意到docs狀態...
對於隊列,其併發操作的最大數量設置爲1,這相當於一個串行隊列。但是,不應該依賴於操作對象的串行執行。
這是否意味着FIFO執行不能保證?
是否可以通過將maxConcurrentOperationCount
設置爲1來將NSoperationQueue
對象用作串行FIFO隊列?NSOperationQueue串行FIFO隊列
我注意到docs狀態...
對於隊列,其併發操作的最大數量設置爲1,這相當於一個串行隊列。但是,不應該依賴於操作對象的串行執行。
這是否意味着FIFO執行不能保證?
在大多數情況下,它將是FIFO。但是,您可以設置NSOperations之間的依賴關係,以便提前提交的操作可以讓其他操作在隊列中傳遞它,直到它的依賴性得到滿足。
這種依賴性管理是文檔顯示無法保證FIFO性能的原因。不過,如果你不使用依賴關係,那麼依靠它應該沒問題。
更新: 的NSOperation也有queuePriority
屬性,它也可能導致操作在非FIFO的順序執行。沒有掛起依賴關係的最高優先級操作將始終首先執行。
NSOperation子類也可能會覆蓋-isReady
,這可能會導致它回到隊列中。
因此,您的隊列上的執行保證爲serial,因爲此隊列中一次只能運行一個操作。但是,蘋果不能保證FIFO;這取決於你和你把作業做什麼
要使用nsInvocationopration 做一個簡單的FIFO,您將需要設置一個操作上的其他 要依靠使用addDependency:方法
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSInvocationOperation *oper1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSth:) object:@"1"];
NSInvocationOperation *oper2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSth:) object:@"2"];
NSInvocationOperation *oper3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSth:) object:@"3"];
[oper2 addDependency:oper1];
[oper3 addDependency:oper2];
//oper3 depends on oper2 wich depends on oper1
//order of execution will ber oper1->oper2->oper3
//Changing the oreder will not change the result
[queue addOperation:oper2];
[queue addOperation:oper3];
[queue addOperation:oper1];
- (void) doSth:(NSString*)str
{
NSLog(str); //log will be 1 2 3
//When you remove the addDependency calls, the logging result that i got where
//different between consecutive runs i got the following
//NSLog(str); //log will be 2 1 3
//NSLog(str); //log will be 3 1 2
}
注意:如果您使用的NSInvocationOperation
然後設置maxConcurrentOperationCount
1將最有可能做的伎倆給你,因爲的isReady將不會對你
但編輯= 1就不會是一個很好的解決方案,如果你是刨去創建自己的NSOperation
子自的NSOperation衍生工具,你可以重寫isReady
功能和返回無,(想象一下一些操作,將需要等待一些數據一臺服務器,以便在這些情況下正常工作),你將返回isReady no
,直到你真的準備好 在這些情況下,您將需要operations
之間添加dependencies
隊列
內從蘋果公司的文檔這相當於一個串行隊列。但是,你不應該依賴於操作對象的串行執行。在操作的準備就緒的變化可改變所得執行順序
你能解釋爲什麼依賴是必要的嗎? –
@BJHomer我已更新我的答案,包括一些日誌記錄 –
您的隊列在示例中沒有像指定的OP那樣的'maxConcurrentOperationCount = 1'。這套裝置是否仍然會發生? –
由文檔中提到的隊列沒有FIFO。如果您確保任何新操作取決於隊列中添加的最後一個操作,並且它一次只能運行一個操作,則可以將其嚴格設置爲FIFO。奧馬爾的解決方案是正確的,但更普遍的,你可以做到以下幾點:
NSOperationQueue* queue = [[ NSOperationQueue alloc ] init];
queue.maxConcurrentOperationCount = 1;
NSOperation* someOperation = [ NSBlockOperation blockOperationWithBlock:^(void) { NSLog(@"Done.");} ];
if (queue.operations.count != 0)
[ someOperation addDependency: queue.operations.lastObject ];
這工作,因爲queue.operations是一個數組:無論你加不重新排序(它不是實例的NSSet)。你也可以簡單的類別添加到您的NSOperationQueue:
@interface NSOperationQueue (FIFOQueue)
- (void) addOperationAfterLast:(NSOperation *)op;
@end
@implementation NSOperationQueue (FIFOQueue)
- (void) addOperationAfterLast:(NSOperation *)op
{
if (self.maxConcurrentOperationCount != 1)
self.maxConcurrentOperationCount = 1;
NSOperation* lastOp = self.operations.lastObject;
if (lastOp != nil)
[ op addDependency: lastOp ];
[ self addOperation:op];
}
@end
,並使用[隊列addOperationAfterLast:myOperation。 queuePriority與FIFO無關,它與作業調度有關。
編輯:在下面的評論之後,如果檢查計數,暫停隊列也是不夠的。我相信這種形式是好的(經過測試,這不會造成競爭狀況,也不會崩潰)。
這種類型的解決方案存在問題。我一直在使用它。偶爾,隊列的lastObject將在檢查queue.operations.count後消失。這很少見,但它發生了。我不確定如何解決它。 –
好點我沒有看到,但是:如果在隊列運行時檢查operations.count,它可能會在我們輸入if條件時結束。我相信編輯後的表格更好更安全:(這裏的測試不會崩潰,而嘗試暫停隊列的測試不起作用(未顯示))。 – Daniel
這也是我也參與的解決方案;創建一個局部變量,防止NSOperation被釋放。 –
執行順序還取決於操作的隊列優先級。 – JeremyP
非常真實。更新。 –
因此,如果我的操作都具有相同的優先級,沒有依賴關係,並且只依賴'isReady'的超類實現(我不覆蓋),它應該導致一個FIFO隊列? – Barjavel