Using Grand Central Dispatch, how can I check if there is a block already running?

我是研究僧i 提交于 2019-12-01 11:31:46
Brad Larson

If you wanted to prevent two blocks of the same type from running at the same time, you could use a dispatch semaphore. With a semaphore set to a count of 1, you can check the semaphore before firing off the block and bail if something is still running. At the end of the block, you signal the semaphore to allow other blocks to be submitted.

I do this in one of my applications to prevent more than one OpenGL ES frame rendering block to be added to the queue at once (preventing buildup of blocks in the queue if a frame takes longer than 1/60th of a second to render). I describe some of this in my answer here, using the following code:

if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0)
{
    return;
}

dispatch_async(openGLESContextQueue, ^{

    [EAGLContext setCurrentContext:context];

    // Render here

    dispatch_semaphore_signal(frameRenderingSemaphore);
});

where frameRenderingSemaphore is created earlier as follows:

frameRenderingSemaphore = dispatch_semaphore_create(1);

If you create a similar semaphore for each tab's download operations, you could do a check to make sure that more than one download isn't being queued up at a time for that tab.

What you need is a simple boolean flag to avoid starting the task again until it is complete (doesn't involve GDC at all). Something like (pseudo-code, not tested, disclaimer, etc):

- (void)something_you_run_in_your_view_did_appear
{
    synchronize(self) {
        if (self.doing_task)
            return;
        self.doing_task = YES;
    }
    start_your_task_here
}

- (void)something_you_run_when_the_task_finishes
{
    synchronize(self) {
        self.doing_task = NO;
    }
}

This pseudo code would work for things like an asynchronous NSURLConnection. I still haven't explored GDC yet, somebody else will need to adapt this to GDC (yourself?).

Note that in this example I'm using a property rather than a simple variable access. This allows you to implement fancier things in the setter, like activating an activity indicator, disabling user interface input, etc. And it also works with subclasses doing their thing when the state of the variable changes in the parent class.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!