我正在使用GCD从互联网上进行一些后台加载。除了一个小缺陷之外,它工作得很好。在我的应用程序中,我有3个选项卡,当单击任何选项卡时,GCD开始为适当的选项卡进行后台加载。如果用户决定从第一个标签转到第二个标签(当GCD已经开始下载第一个标签的数据时),然后再次返回到第一个标签。GCD将启动另一个后台线程(即使第一个后台线程尚未完成数据下载)。
那么,有没有办法检查后台线程当前是否正在运行?这样,如果用户选择快速地来回切换选项卡(出于某种原因),它就不会启动多个后台线程。
发布于 2011-07-15 01:47:41
如果您希望防止同一类型的两个块同时运行,则可以使用分派信号量。在信号量设置为1的情况下,您可以在触发块之前检查信号量,如果有什么东西仍在运行,则退出。在块的末尾,您向信号量发出信号,以允许提交其他块。
我在我的一个应用程序中这样做是为了防止一次将多个OpenGL ES帧渲染块添加到队列中(如果一个帧的渲染时间超过1/60秒,则防止在队列中堆积块)。我在我的答案here中使用以下代码描述了其中的一些内容:
if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0)
{
return;
}
dispatch_async(openGLESContextQueue, ^{
[EAGLContext setCurrentContext:context];
// Render here
dispatch_semaphore_signal(frameRenderingSemaphore);
});其中,之前创建frameRenderingSemaphore的方式如下:
frameRenderingSemaphore = dispatch_semaphore_create(1);如果您为每个选项卡的下载操作创建了一个类似的信号量,则可以进行检查,以确保该选项卡的下载队列中不会同时有多个下载。
发布于 2011-07-15 01:30:30
您需要的是一个简单的布尔标志,以避免在任务完成之前再次启动该任务(根本不涉及GDC )。类似于(伪代码、未测试、免责声明等):
- (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;
}
}这个伪代码适用于异步NSURLConnection之类的东西。我还没有探索过GDC,其他人需要将其适应GDC (您自己?)。
请注意,在本例中,我使用的是属性,而不是简单的变量访问。这允许你在setter中实现一些更奇特的东西,比如激活一个活动指示器,禁用用户界面输入等等。当父类中变量的状态改变时,它也可以用子类来做他们自己的事情。
https://stackoverflow.com/questions/6694439
复制相似问题