2016-05-31 87 views
1

在客觀C, 我讓我的程序中使用while循環在iOS編程中使用while(true)語句是一種有效的方法?

doInitialize() 
{ 
dispach_group_t loadDataGroup=dispatch_group_create(); 
dispatch_group_async(loadDataGroup,...get_global_queue(..),0),^{ 
    renewauth(); 
} 
dispatch_group_notify(loadDataGroup,...get_global_queue(..),0),^{ 
    //Do other tasks once renew session has completed... 
} 
} 
renewauth() 
{ 
RenewAuthTokenInProgress=true; 
startRenewThread(); 
**while (RenewAuthTokenInProgress);** 
} 

反過來startRenewThread()函數裏面也進行dispatch_async操作等。所以我必須使renewAuth()等待。

一旦更新成功,startRenewThread中的異步任務將更新bool變量。

除了dispatch_groups之外,還有更好的方法嗎? 讓其他線程與while(true)語句等待是否好?

+0

忙碌的等待是一個可怕的想法。爲什麼你要在後臺運行這個更新功能? – Thilo

+0

如果你使用異步路由,dispatch_groups有什麼問題? – Thilo

+1

假設RenewAuthTokenInProgress保持一段時間,然後是你的iPhone會變熱。您將以100%運行其中一個內核。它也會使你的電池變平。 – TJA

回答

6

的Manoj庫馬爾,

使用while循環要等到布爾變量的變化是不是解決問題的正確途徑。這裏有幾個這個方法的問題

  1. 你的CPU是不必要的負擔有定期檢查變量。

  2. 這將清楚地表明,開發人員沒有太多配備編程和語言功能的基本技能。

  3. 如果因爲任何原因你的變量永遠不會改變,那麼你的CPU永遠不會停止檢查while循環中的bool值,並阻止在同一線程上執行進一步的代碼。

這裏有一些正確的方法:

  1. 塊或倒閉:利用塊來當RenewAuthToken完成異步執行代碼。

  2. 代表:如果塊更難理解,請在完成RenewAuthToken時使用委託並觸發委託。

  3. 通知:爲需要在RenewAuthToken完成時需要響應的類添加通知的觀察者,並從異步抽出通知並讓類捕獲它執行代碼。

  4. 鎖:如果有必要,直到響應來使用鎖來控制線程執行,而不是使用以阻止線程的執行while循環

EDIT

如尖由fogmeister在評論

如果您阻止主線程太長時間(true)循環然後 應用程序實際上將iOS的看門狗被終止,因爲它會 假設它已經崩潰

請看看鏈接:通過提供fogmeister understand iOS watchdog termination reasons

希望它能幫助。

+3

還有一些要注意的事情。如果使用'while(true)'循環阻塞主線程時間過長,那麼應用程序實際上將被iOS Watchdog終止,因爲它會認爲它已經崩潰。 – Fogmeister

+0

@fogmeister:Bingo :)投票支持:) –

+1

如果你想要添加一個鏈接https://developer.apple.com/library/ios/technotes/tn2151/_index.html搜索'8badf00d'會顯示看門狗終止的原因。 – Fogmeister

1

我相信你需要什麼這是一個semaphore,如:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 

dispatch_semaphore_t sem = dispatch_semaphore_create(0); 
__block BOOL done = FALSE; 
while (true) { 

    [self someCompletionMethod completion:^(BOOL success) { 

     if(success) { // Stop condition 
      done = TRUE; 
     } 
     // do something 
     dispatch_semaphore_signal(sem); // This will let a new iteration 
    }]; 

    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); 

    if(done) { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      // Dispatch to main 
      NSLog(@"Done!"); 
      break; 
     }); 
    } 
} 

}); 

信號燈是由曾經那麼卑微艾茲赫爾·戴克斯特拉介紹給世界一個老派的線程概念。信號量是一個複雜的話題,因爲它們建立在操作系統功能的複雜性之上。

你可以在這裏看到一個教程的信號,並檢查了更多的鏈接:https://www.raywenderlich.com/63338/grand-central-dispatch-in-depth-part-2

我希望這可以幫助你。

+0

沒有冒犯,但信號燈通常是懶惰不處理異步模式的處理的證據。 – vadian

+1

沒有冒犯,但信號燈往往是一個處理異步事件的好方法。對於這個特定的問題,儘管很可能不是正確的選擇。還有一種先進技術,可能超出OP。 – gnasher729

+0

有沒有進攻,謝謝你的兩個意見,我相信這是相當意見,我同意gnasher729,但我真的明白你的意思vadian。 –

0

你所做的絕對是致命的。它阻止正在運行的線程(可能是主線程),因此UI被凍結。它在100%的負載下運行一個內核,沒有任何理由使電池快速排空並加熱電話。這會讓你有些非常非常不開心的顧客,或者非常非常開心的前顧客。

像這樣的任何東西都必須在後臺運行:startRenewThread應該觸發一些設置RenewAuthTokenInProgress = NO的動作,並設置是否有新的令牌,然後觸發進一步的動作。

這是一個絕對必要的編程模式在iOS(和我所知的Android)上。

相關問題