当应用程序转换到后台时,我偶尔会遇到与并发线程上未正确完成的任务有关的崩溃。
所以我有3个帖子:
方案如下:
在applicationDidEnterBackground:
处理程序(肯定在thread A
上执行)中,thread B
上开始了一个长时间运行的任务,以完成所有正在进行的操作(保存应用程序状态,关闭套接字)等)。在这个任务中,我需要等到套接字正确完成thread C
上的工作,然后才能继续执行这个长时间运行的任务。
以下是简化代码:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Some synchronous task.
[stateManager saveState];
// Here I need to wait until the socket finishes its task.
...
// Continuing of the long-running task.
...
}
完成此任务的可接受方式是什么。如果我做这样的事情,可以吗?
while (socket.isConnected)
{
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
// Continuing of the long-running task.
或者我当前的架构可能有问题,我需要使用NSOperation
以某种方式序列化异步任务?
更新:@Rob Napier建议使用dispatch_semaphore
APIs来解决问题。
答案 0 :(得分:1)
首先,不要将这些视为线程,如果您使用NSThread
或performSelectorInBackground:
(或者更糟糕的是,pthreads)创建线程,请不要这样做。使用GCD。 GCD创建队列。队列顺序块,最终在线程上运行,但线程是实现细节,并且没有队列到线程的1:1映射。有关详细信息,请参阅Migrating Away from Threads。
对于如何等待其他操作的问题,您可能需要的工具是dispatch_semaphore
。您创建信号量并将其交给两个操作。然后,当您想要等待某事时,请拨打dispatch_semaphore_wait
;当您想表明发生了某些事情时,请dispatch_sempahore_signal
。有关更多示例代码,请参阅Using Dispatch Semaphores to Regulate the Use of Finite Resources。 "有限资源"在这种情况下是"套接字。"您希望等到其他部分完成后再使用它并将其返回到池中。
即使您使用手动线程,信号量也能正常工作,但我不能强调您不应该进行手动线程化。所有并发都应该通过GCD进行管理。这是iOS中整体并发管理的重要工具。
答案 1 :(得分:1)
我会将NSOperation
与依赖项一起使用。
所以,你有任务
A - 主线程 - 又名'入口点'
B - 在背景中运行的重男孩
C - 套接字完成后运行的其他东西很重
你有一系列的操作,彼此依赖:
OperationB - > OperationSend - > OperationC