2012-03-31 11 views
4

私は、アプリケーションがバックグラウンドにプッシュされても、完了したい長い実行中のタスクを持っています。ドキュメントから私はこれを行う方法はbeginBackgroundTaskWithExpirationHandlerを使用することであることがわかります:非同期機能とは、次のコードスニペットのように実行中のタスクを開始します。iOS:終了時にバックグラウンドタスクコードブロックが呼び出されるのはいつですか?

UIApplication* application = [UIApplicationsharedApplication]; 
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{ 
    // Clean up any unfinished task business by marking where you. 
    // stopped or ending the task outright. 

    [application endBackgroundTask: bgTask]; 
    bgTask = UIBackgroundTaskInvalid; 
}]; 

// Start the long-running task and return immediately. 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

    // Do the work associated with the task, preferably in chunks. 
     for (int i = 0; i < 3; i++){ 

     [self doChunkOfWork]; 
    } 

    // end work 
    [application endBackgroundTask:bgTask]; 
    bgTask = UIBackgroundTaskInvalid; 
}); 

は、今私は2番目のコードブロックは非同期で実行されることを理解してアプリケーションが通知され、タスクが無効とマークされていれば、最初のコードブロックがどのような状況で実行され、どのように第1および第2ブロックがどのように関連付けられるのか教えてくれますか?それは単に私がタスクを開始し、次に行うことは、dispatch_asyncを呼び出して、2つのブロックが関連付けられることです。

答えて

5

これらのブロックは、「魔法のように」関連していません。

2番目のブロックは、キューに入れられ、非同期に実行されます。最初のブロックはonly ever be called by the systemがあればします:

  1. アプリケーションがバックグラウンドに送られる(すなわち、他のアプリへのユーザースイッチ)(現在のiOSバージョンの)約10分
  2. あなたの第二のブロックの[self doChunkOfWork]ブロック。

-doChunkOfWorkもしブロックは、[application endBackgroundTask:bgTask]が呼び出されることはありません、そしてシステムは、当然でしょう!-thinkあなたはまだ仕事をやっています。 iOSはバックグラウンドで作業できる時間の制限を設定し、この制限を超えると期限切れハンドラ(最初のブロック)を呼び出します。

有効期限ハンドラの現在の実装では、タスクが完了したとすぐにマーク付けされます。その時点でアプリケーションは実行されなくなり、まだdoChunkOfWorkが実行されている場合は一時停止されます。 (実際には、アプリケーションのスレッドはすべて一時停止されます)。

今後、ユーザーはアプリに戻ることがあります。あなたのスレッドはその後再開され、doChunkOfWorkはそれがあった場所で実行を継続します。

+2

上記の 'doChunkOfWork'がまだ進行中で、次にアプリケーションがバックグラウンドになると、有効期限ハンドラが完了したタスクとしてすでにマークされているため、システムに時間がかかりません。これはおそらくあなたが望むものではありません。 –

+0

右しかし、この問題をどのように解決することを提案しますか? – Dev

+1

実際に、有効期限ハンドラによって通知されたときにタスクをキャンセルします。 'NSOperation'を使用している場合は、それを[キャンセルする]に変更する必要があります(http://developer.apple.com/library/ios/documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html#//apple_ref/doc/uid/TP40004591-RH2-SW18)、満了ハンドラから 'cancel'を呼び出してください。あなたのハンドラで何か非ブロック化をしているなら、 'beginBackgroundTaskWithExpirationHandler:'への新しい呼び出しでキャンセルし、後で再起動するようにフラグを設定してください。 –

関連する問題