当该方法本身正在进行异步任务时,如何跳过对该方法的预定调用?

How to skip scheduled call to a method when an asynchronous task is ongoing on that method itself?

假设我有一个方法可以执行一些异步任务。假设它刷新用户的访问权限,可能需要几分钟,具体取决于互联网连接速度或其他因素。

我必须定期调用此方法(即使用 NSTimer 的方法 scheduledTimerWithTimeInterval: target: selector: userInfo: repeats: 的预定调用)

-(void)refreshPermission {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // do something that takes a few minutes
    });
}

现在我称这个方法为timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(refreshPermission) userInfo:nil repeats:YES];。也就是说,此调用每 10 秒触发一次。

What I need to do is, I need to somehow skip one (or, more than one) scheduled call to this method if something is happening inside that asynchronous block (Let's say, user's access permission hasn't been updated).

但是一旦阻止完成(即用户的访问权限已更新),应该恢复使用定时器的预定呼叫。

关于如何完成此操作的任何想法或示例?

我认为您可以使用 Bool 变量来完成。您可以全局声明 Bool 变量,并通过使用其状态在函数调用中管理您的任务。

在方法中refreshPermission

-(void)refreshPermission {
   if(!isExecuting){

      isExecuting = YES;
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // Perform your tasks

         isExecuting = NO;
      }
    }
}

我想到了这个方法。从@Sunny 的回答中得到灵感。

它对我有用。但任何有关此实现的建议都将受到赞赏。

-(void)refresh {
    NSLog(@"Refresh called");
    NSLock *theLock = [[NSLock alloc] init];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSLog(@"Async task assigned");

        if(!isExecuting){

            [theLock lock];
            isExecuting = YES;
            [theLock unlock];

            // Perform your tasks
            NSLog(@"Async task started");
            [NSThread sleepForTimeInterval: 13.0];  // for testing purpose
            NSLog(@"Async task completed");

            [theLock lock];
            isExecuting = NO;
            [theLock unlock];

        }
    });
}

这里isExecuting是包含class的一个实例变量。在设置用于定期调用该方法的实际计划计时器之前,它已设置为 isExecuting = NO;

这里我使用 NSLock 来保证当一个线程正在执行它的任务时没有其他线程可以更改 isExecuting 的值。我添加此锁定是因为每次调用 -(void)refresh 方法时,都有可能多个线程有资格执行和更改 isExecuting 的值。所以最好在改变共享变量的值时让它成为线程保存。