dispatch_after限制为10秒?

时间:2021-11-04 11:58:42

I'm developing an app which is running in background. Sometimes I need to tell the user that something is happenning so I play a sound a certain number of times. To do that I made a timer but the problem is that It cannot exceed 10s of the total delayed time, after that, there are no more sounds (but the app is still running). I've checked this behavior in foreground mode and it works perfectly.

我正在开发一个在后台运行的应用程序。有时我需要告诉用户发生了什么事情,所以我播放了一定次数的声音。为此我做了一个计时器,但问题是它不能超过总延迟时间的10s,之后,没有更多的声音(但应用程序仍在运行)。我在前台模式中检查了这种行为,它完美无缺。

This is my code when I need to inform the user:

当我需要通知用户时,这是我的代码:



    AudioServicesPlaySystemSound(alarma);
    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
    numAlarm = 1;  
    NSTimeInterval delay_in_seconds = 2.0;
    dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW,delay_in_seconds*NSEC_PER_SEC);
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
    dispatch_after(delay,queue,^{
        [self fiBGTemps:ALARM];
    });

and the "fiBGTemps" is something like this,

而“fiBGTemps”是这样的,


- (void)fiBGTemps:(int)sender
{
    switch (sender){
        case TEMP_SCAN:
            (…)
            break;
        case ALARM:
            if (numAlarm>0 && numAlarm&ltNUM_ALARM)
            {
                AudioServicesPlaySystemSound(alarma);
                AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
                NSTimeInterval delay_in_seconds = 2;
                dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW,delay_in_seconds*NSEC_PER_SEC);
                dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
                dispatch_after(delay,queue,^{
                    [self fiBGTemps:ALARM];
                });
                numAlarm++;
            }
            break;
    }
}

Is that behavior normal? Am I missing something?

这种行为是正常的吗?我错过了什么吗?

Thanks

谢谢

Kanick

Kanick

3 个解决方案

#1


1  

Problem solved.

问题解决了。

This is what happens. When an app is running in background and and it is executed a task, this task is running in background as well but the system allows only a certain amount of time (10s apron.) in order to safe battery. So it is only for a specific tasks (localization, download, etc.).

这就是发生的事情。当应用程序在后台运行并执行任务时,此任务也在后台运行,但系统只允许一定的时间(10s围裙。)以便安全使用电池。因此它仅适用于特定任务(本地化,下载等)。

I my case I need a little more time so the solution is to define the task as a UIBackgroundTask in such a way that will be the task who notify the system when it is completed and thus can be terminated.

我的情况我需要更多的时间,因此解决方案是将任务定义为UIBackgroundTask,这将是在完成时通知系统并因此可以终止的任务。

this is the code where it is called the task:

这是它被称为任务的代码:



    UIApplication *application = [UIApplication sharedApplication];
    __block UIBackgroundTaskIdentifier background_task;
    background_task = [application beginBackgroundTaskWithExpirationHandler: ^{
        [application endBackgroundTask: background_task];
        background_task = UIBackgroundTaskInvalid;
    }];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self fiBGTemps:@(ALARM)];
        [application endBackgroundTask: background_task];
        background_task = UIBackgroundTaskInvalid;
    });

And here you can see the discussion on the Apple Forums where they explain this better than me.

在这里你可以看到关于Apple论坛的讨论,他们在那里比我更好地解释了这一点。

AppleForums discussion

Apple论坛讨论

I hope this helps.

我希望这有帮助。

Kanick

Kanick

#2


0  

You can try with re-setting the delay value after it exceed 10s of the total delayed time or may be after it has played sound for certain amount of time.

您可以尝试在延迟时间超过总延迟时间的10秒后重新设置延迟值,也可以在延迟值播放一段时间之后再尝试。

#3


0  

I suspect that chaining asynch blocks to play sounds at regular intervals is a bit of an overkill. Perhaps something simpler along the following lines would be easier to understand and maintain:

我怀疑链接asynch块以定期播放声音有点过分。沿着以下几行简化可能更容易理解和维护:

// To initiate the alarm:
[self fiBGTemps: ALARM];

- (void)fiBGTemps:(int)sender
{
    switch (sender) {
       ...
       case ALARM:
           dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
                int count = 0;
                while (count < NUM_ALARM /* AND not interrupted by user? */) {
                    sleep(2);
                    AudioServicesPlaySystemSound(alarma);
                    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
                    count++;
                }
            });
            break;
        ...
    }
}

#1


1  

Problem solved.

问题解决了。

This is what happens. When an app is running in background and and it is executed a task, this task is running in background as well but the system allows only a certain amount of time (10s apron.) in order to safe battery. So it is only for a specific tasks (localization, download, etc.).

这就是发生的事情。当应用程序在后台运行并执行任务时,此任务也在后台运行,但系统只允许一定的时间(10s围裙。)以便安全使用电池。因此它仅适用于特定任务(本地化,下载等)。

I my case I need a little more time so the solution is to define the task as a UIBackgroundTask in such a way that will be the task who notify the system when it is completed and thus can be terminated.

我的情况我需要更多的时间,因此解决方案是将任务定义为UIBackgroundTask,这将是在完成时通知系统并因此可以终止的任务。

this is the code where it is called the task:

这是它被称为任务的代码:



    UIApplication *application = [UIApplication sharedApplication];
    __block UIBackgroundTaskIdentifier background_task;
    background_task = [application beginBackgroundTaskWithExpirationHandler: ^{
        [application endBackgroundTask: background_task];
        background_task = UIBackgroundTaskInvalid;
    }];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self fiBGTemps:@(ALARM)];
        [application endBackgroundTask: background_task];
        background_task = UIBackgroundTaskInvalid;
    });

And here you can see the discussion on the Apple Forums where they explain this better than me.

在这里你可以看到关于Apple论坛的讨论,他们在那里比我更好地解释了这一点。

AppleForums discussion

Apple论坛讨论

I hope this helps.

我希望这有帮助。

Kanick

Kanick

#2


0  

You can try with re-setting the delay value after it exceed 10s of the total delayed time or may be after it has played sound for certain amount of time.

您可以尝试在延迟时间超过总延迟时间的10秒后重新设置延迟值,也可以在延迟值播放一段时间之后再尝试。

#3


0  

I suspect that chaining asynch blocks to play sounds at regular intervals is a bit of an overkill. Perhaps something simpler along the following lines would be easier to understand and maintain:

我怀疑链接asynch块以定期播放声音有点过分。沿着以下几行简化可能更容易理解和维护:

// To initiate the alarm:
[self fiBGTemps: ALARM];

- (void)fiBGTemps:(int)sender
{
    switch (sender) {
       ...
       case ALARM:
           dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
                int count = 0;
                while (count < NUM_ALARM /* AND not interrupted by user? */) {
                    sleep(2);
                    AudioServicesPlaySystemSound(alarma);
                    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
                    count++;
                }
            });
            break;
        ...
    }
}