2012-08-28 30 views
3

我執行以下方法:在這種情況下,主隊列/當前隊列和主線程/後臺線程之間的區別?

MotionHandler.m

-(void)startAccelerationUpdates 
{ 
    [motionManagerstartDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]withHandler:^(CMDeviceMotion *motion, NSError *error){.....} 
} 

在後臺線程,如下所示:

[currentMotionHandler performSelectorInBackground:@selector(startAccelerationUpdates) withObject:nil]; 

但是上述方法使用main Queue(其是在主線程)來執行必要的更新,即使我在後臺線程調用它..所以加速更新正在執行後臺線程或ma在線程中,我很困惑..?

更有趣的是,當我在後臺線程上再次調用上述方法時,這次使用current Queue,我沒有更新。有人可以解釋一下運行之間的區別:

1. a background thread but on the main queue 

2. a background thread but on the current queue 

3. the main thread but on the main queue 

4. the main thread but on the current queue 

在當前的實現?謝謝!

回答

5

我會給它一個鏡頭。首先,沒有被NSOperationQueue類的引用告知,我們無法推斷'mainQueue'會在哪個線程上運行。讀取它,我們看到實際上該隊列在UI使用的mainThread上運行,因此您可以更新發布到該隊列的操作中的UI。雖然沒有說明,但這些操作必須是串行的,因爲它們是由runLoop執行的(它可能會被搶佔,而不是100%肯定)。

currentQueue的用途是,運行操作可以確定它們所在的隊列,因此它們可以將新操作排隊在該隊列上。

  1. 後臺線程,但主隊列

不可能的 - 該的NSOperation的mainQueue總是與mainThread有關。

  1. 後臺線程,但是,從當前隊列

當你創建一個NSOperationQueue,並添加NSOperations它,那些得到由隊列管理後臺線程運行。任何給定的操作都可以查詢它的線程,並且該線程在運行時不會更改。也就是說,對該隊列的第二個操作可能會在不同的線程上運行。

  1. 主線程,但主隊列

見1)

  1. 主線程,但是,從當前隊列

如果排隊操作給mainQueue(這是我們所知道的是總是在mainThread),你問的currentQueue,它將返回mainQueue:

[NSOperationQueue currentQueue] == [NSOperationQueue mainQueue]; 
+1

謝謝大家既爲你的答案,很受啓發哉!但是,我經歷了NSOperation&NSOperationQueue類的引用,並且沒有關於如何執行該操作的指導原則,即如何在後臺線程上創建隊列並在該隊列上運行(例如加速更新)。這是明顯需要做的事情,因爲在後臺運行加速更新是基於文檔的最安全的方法 –

+1

如果您創建自己的隊列= NSOperationQueue * foo = [NSOperationQueue new] ;,則將操作排隊,將在後臺線程上運行而不是mainThread。閱讀Apple Concurrency Guide。您可能會發現,塊現在是更好的選擇。在使用NSURLConnections時,我只使用NSOperations來實現併發。你可以看到在Github上一個簡單的項目中,我寫道:https://github.com/dhoerl/NSOperation-WebFetches-MadeEasy - 你會看到如何創建一個隊列,併發操作等。它的一個小項目一些文件。 –

+0

謝謝大衛我會看看你的項目,看看如何正確實施你的建議。 –

4

您正在使用的線程混淆隊列。特別是由於NSOpertionQueue已被重寫,使用GCD,有隊列和特定線程之間沒有什麼聯繫(除主線程的特殊情況)。

操作/塊/任務 - 無論你怎麼稱呼他們 - 插入到隊列中,「工作線程(S)」拉斷這些並執行它們。你幾乎無法控制哪一個確切的線程將執行工作 - 除了主隊列之外。 注意,這是不完全正確的,因爲它是一個簡化,但它是真的不夠,除非你正在做的事情相當先進和具體。

因此,你的4種情況都不是有意義的,例如,你不能在「後臺線程但在主隊列上」運行某些內容。

現在,您的方法startAccelerationUpdates明確告訴CMMotionManager將您的處理程序放在主隊列中。因此,當調用startAccelerationUpdates時,它會在運行的任何線程中運行,但會調度要在主線程上執行的處理程序。

要稍微複雜的事情,你是通過調用performSelectorInBackground調用startAccelerationUpdates方法。再次,你不知道哪個線程將實際調用startAccelerationUpdates,但它不會成爲主線程。

但是,在你的情況下,所有線程正在調用startAccelerationUpdates,它正在啓動運動更新,並告訴它們在主線程(通過主隊列)上處理。

現在,這裏的東西,從使用主隊列來處理運動事件從文檔勸阻你,直接...

因爲處理的事件可能會以較高的速率到達,使用的主要操作隊列不推薦。

不幸的是,你的發言

什麼是更有趣的是,當我再次呼籲 後臺線程上面的方法,但使用當前隊列這個時候,我得到 沒有更新。

沒有提供足夠的信息來確定您嘗試了什麼,如何嘗試它,或者您爲什麼認爲它不起作用。所以,我會猜測......這可能是錯誤的。

我將輸入the current Queue

我假設你的意思是你替代[NSOperationQueue mainQueue][NSOperationQueue currentQueue]

好吧,讓我們來看看是什麼一樣。而不是使用主隊列,您將使用「其他」隊列。哪一個?好吧,讓我們來看看文檔:

currentQueue

返回目前推出的 操作的操作隊列。

+(ID)currentQueue

返回值

啓動該操作或零如果隊列無法確定操作隊列。

討論

您可以使用此方法從正在運行的操作 對象中去啓動它的操作隊列的引用。 從正在運行的操作 的上下文外調用此方法通常會導致返回nil。

請注意討論部分。如果調用此當你不運行的是從一個NSOperationQueue調用的操作時,你會得到nil,這意味着將不會有排隊在其上放置您的處理程序。所以,你什麼也得不到。

您必須指定哪個隊列將被使用,如果你想使用NSOperationQueue以外的主隊列。所以,如果這是你想要的路線,只需創建你自己的操作隊列來處理運動事件,然後關閉!

祝你好運!