从并发线程等待事件的正确方法

时间:2015-11-03 16:12:28

标签: ios objective-c multithreading

当应用程序转换到后台时,我偶尔会遇到与并发线程上未正确完成的任务有关的崩溃。

所以我有3个帖子:

  1. A(主要)。
  2. B(由GCD管理)。
  3. C(手动创建以处理密集的套接字操作)。
  4. 方案如下:

    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来解决问题。

2 个答案:

答案 0 :(得分:1)

首先,不要将这些视为线程,如果您使用NSThreadperformSelectorInBackground:(或者更糟糕的是,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 - 套接字完成后运行的其他东西很重

  1. “B”的繁重任务是OperationB
  2. 假设您的套接字框架能够在当前线程中运行同步? - 那么这是你的OperationSend
  3. 在后台做其余的事 - OperationC
  4. 你有一系列的操作,彼此依赖:

    OperationB - > OperationSend - > OperationC