简体   繁体   中英

How to run a non main queue in a background state?

Please take a look at this very simple piece of code:

dispatch_async(dispatch_get_main_queue(), ^{
   
    for (int i = 0; i < 100; i++)
    {
        NSLog(@"LOOP %d", i);
        sleep(1);
    }
});

If I send my app to the background state it is still running. Yet if I put the execution onto a non main queue like this:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    
    for (int i = 0; i < 100; i++)
    {
        NSLog(@"LOOP %d", i);
        sleep(1);
    }
});

then the execution is suspended when my app is going to the background. Is it possible to make it run in a background state when dispatched on a non main queue?

I need to mention that I'm running my app with these background modes enabled:

<key>UIBackgroundModes</key>
<array>
    <string>bluetooth-central</string>
    <string>voip</string>
</array>

In addition to using performExpiringActivityWithReason , you can use the UIBackgroundTaskIdentifier API:

// Perform the task on a background queue.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
   // Request the task assertion and save the ID.
   self.backgroundTaskID = [[UIApplication sharedApplication]
              beginBackgroundTaskWithName: @"Finish Pending Tasks" expirationHandler:^{
       // End the task if time expires.
       [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskID];
       self.backgroundTaskID = UIBackgroundTaskInvalid;
   }];
        
   // Add your code here.
        
   // End the task assertion.
   [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskID];
   self.backgroundTaskID = UIBackgroundTaskInvalid;
};

The expiration handler is what gets called before the app is killed, but don't plan on doing computationally expensive tasks using this method since the OS has system-wide time limits which are out of the developer's control.

If you need to perform specific tasks in the background for certain system events like network fetches, then consider using a Background Mode.

bg模式ios

The advantage of using the UIKit API, in this case, is you can query [[UIApplication sharedApplication] backgroundTimeRemaining] within your for loop to perform any last-minute cleanup steps.

Note that if you're using App Extensions Apple recommend using the NSProcess API, so advice will vary depending on the use case.

Please try using NSProcessInfo performExpiringActivityWithReason API

[[NSProcessInfo processInfo] performExpiringActivityWithReason:@"myReason" usingBlock:^(BOOL expired)
{
  // This block is run on a separate (background) thread
  // Put your code here...
}

please note this is only a request for some additional CPU time on a process that is being backgrounded... you cannot run background code indefinitely.

The block will be invoked a 2nd time with expired == YES when you're about to be killed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM