6

我有一些長時間運行的進程,即使應用程序在後臺運行,我也想運行它。我正在調用應用程序的beginBackgroundTaskWithExpirationHandler:方法,並在expirationBlock中調用應用程序的endBackgroundTask。 這裏是實現:beginBackgroundTaskWithExpirationHandler調用endBackgroundTask但沒有結束過程

__block UIBackgroundTaskIdentifier task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 
    [[UIApplication sharedApplication] endBackgroundTask:task]; 
    task = UIBackgroundTaskInvalid; 
}]; 
dispatch_queue_t queue = dispatch_queue_create("com.test.test1234", DISPATCH_QUEUE_SERIAL); 
dispatch_async(queue, ^{ 
    // My Task goes here 
}); 

在某些情況下,我的序列隊列有更多的任務要執行,不能由制度規定的時間內完成。所以到期塊將執行,並在那我結束UIBackgroundTaskIdentifier但不停止調度過程(我甚至不能取消派遣)。

蘋果的文件說:

每次調用beginBackgroundTaskWithName:expirationHandler:或beginBackgroundTaskWithExpirationHandler:方法生成一個獨特的標記與相應的任務關聯起來。當您的應用完成一項任務時,必須使用相應的令牌調用endBackgroundTask:方法,以讓系統知道任務已完成。未能調用後臺任務的endBackgroundTask:方法將導致應用程序終止。如果您在啓動任務時提供了到期處理程序,系統會調用該處理程序,併爲您提供最後一次結束任務並避免終止的機會。

所以,根據這個如果我不叫endBackgroundTask:我的應用程序將被終止,這是可以的。

我的問題是:在我目前的實施中,如果我在expirationHandler塊中調用endBackgroundTask:,並且我的調度隊列的任務沒有完成,該怎麼辦?我的應用程序將被終止或將被暫停?

感謝

+0

如果你叫做endBackgroundTask:在任何你的隊列裏。它只是暫停你的應用程序,讓應用程序進入睡眠。 –

+0

@chiragshah所以這不能成爲看門狗殺死我的應用程序的權利?只有當我錯過'endBackgroundTask'時,看門狗才會殺死應用程序? –

+0

是的,我做了同樣的想法,在我的應用程序,它可以正常工作 –

回答

11

這裏有一些情況下,你需要同時使用beginBackgroundTaskWithExpirationHandler否則你的應用程序將terminate處理。

場景1:您的應用正在運行Foreground。你開始beginBackgroundTaskWithExpirationHandler然後進入Background模式。你的應用長期保持活力。

情景2:您的應用正在運行Foreground。你開始beginBackgroundTaskWithExpirationHandler然後進入Background模式。然後回到Foreground模式,並且你沒有調用endBackgroundTask,那麼你的應用程序仍然是execute background queue,所以它會擴展該進程的下一個3 minute(在IOS 7引入之前,在IOS 7之前,進程執行時間是10分鐘)。所以你必須取消後臺隊列和任務從後臺隊列中出來並進入前臺隊列

所以這裏是顯示你的代碼。什麼是處理後臺進程的最佳方式。

第1步:聲明__block UIBackgroundTaskIdentifier bgTask作爲全局變量。

步驟2:在applicationDidEnterBackground中添加以下代碼。

- (void)applicationDidEnterBackground:(UIApplication *)application { 

     bgTask = [application beginBackgroundTaskWithExpirationHandler:^{ 
     bgTask = UIBackgroundTaskInvalid; 
      }]; 

} 

第3步:停止後臺任務處理一次應用進來前臺模式。

- (void)applicationWillEnterForeground:(UIApplication *)application { 
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 

    [[UIApplication sharedApplication] endBackgroundTask:bgTask]; 

} 
+0

謝謝你的答案。在場景2中,如果我在應用程序到達前臺時不調用endBackgroundTask,該怎麼辦?我已經在到期塊中調用了endBackgroundTask。 –

+0

編譯器會理解您的後臺隊列仍然執行,因此在該編譯器終止您的應用程序之後的3分鐘內執行擴展。這是發生在我身上的情景。 –

1

如果您在到期處理程序中沒有撥打endBackgroundTask,您的應用程序將被終止。

一旦你在你的過期處理程序中調用endBackgroundTask,你只是告訴操作系統「好吧,我完成了保存關鍵任務,現在取決於你。之後,您的應用可能會暫停一段時間,稍後終止,或者可能會根據系統資源立即終止。

+0

或者由於其他任務,它可能會停留在後臺... – Honey