DispatchQueue绑定到确切的线程

时间:2018-09-18 15:19:20

标签: ios multithreading grand-central-dispatch

im正在开发一个应用,该应用使用一些框架通过openGL绘制3D人员。这个框架要求我从完全相同的线程中调用draw()方法。

因此,我创建了一个串行DispatchQueue,并在其中启动了CADisplayLink,以60FPS的速度调用draw()。我必须从这个确切的线程中调用其他几种方法,例如start()stop()。这使队列成为我的理想解决方案。

您可能知道DispathQueue不能保证在同一线程上执行每个任务。这对我来说压力很大,因为它可能会破坏我的应用程序。

我真的不喜欢创建NSThread并在其上实现自己的队列的想法。

有什么方法可以将DispatchQueue绑定到确切的线程?也许可以绑定NSOperationQueue?

1 个答案:

答案 0 :(得分:1)

Apple Documentation说:

  

在向应用程序添加并发性时,分派队列提供了一些优于线程的优点。最直接的好处是工作队列编程模型的简单性。使用线程,您必须为要执行的工作以及线程本身的创建和管理编写代码。调度队列使您可以专注于实际要执行的工作,而不必担心线程的创建和管理。而是由系统为您处理所有线程的创建和管理。优点是该系统比任何单个应用程序都能够更有效地管理线程。系统可以根据可用资源和当前系统状况动态扩展线程数量。此外,与您自己创建线程相比,系统通常能够更快地开始运行任务。

简单来说,您要么使用调度队列,简单地创建它们并向他们发送工作,要么使用NSThreadNSRunLoop s,创建它们,进行设置,发送工作给他们,并可能阻止他们。

详细信息:

NSThread / NSRunLoop

创作:

self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadMainRoutine) object:nil];
[self.thread start];

开始/管理:

- (void)threadMainRoutine
{
    // Set the runLoop variable, to signal this thread is alive
    self.runLoop = [NSRunLoop currentRunLoop];

    // Add a fake Mach port to the Run Loop, to avoid useless iterations of the main loop when the
    //  thread is just started (at this time there are no events added to the run loop, so it will
    //  exit immediately from its run() method)
    [self.runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];

    //--- Thread main loop
    while (thread_KeepRunning)
    {
        // Run the run loop. This function returns immediately if the RunLoop has nothing to do.
        //  NOTE: THIS STATEMENT:
        //      [self.runLoop run];
        //      DOES NOT WORK, although it is equivalent to CFRunLoopRun();
        CFRunLoopRun();
    }

    // Unset the runLoop variable, to signal this thread is about to exit
    self.runLoop = nil;
}

添加要执行的工作:

[self performSelector:@selector(mySelector:) onThread:myThread withObject:myObject waitUntilDone:YES];

关机:

- (void)stop
{
    if (self.thread) {
        while (self.thread.isExecuting) {
            thread_KeepRunning = NO;
            CFRunLoopStop([self.runLoop getCFRunLoop]);
            [NSThread sleepForTimeInterval:0.1f];
        }
    }

    self.runLoop = nil;
    self.thread = nil;
}

调度队列

创作:

dispatch_queue_t myQueue = dispatch_queue_create("My Queue", DISPATCH_QUEUE_SERIAL);

开始:

dispatch_resume(myQueue);

添加要执行的工作:

dispatch_async(myQueue, (void)^ {
    // put the work into this block
});

关机:

dispatch_suspend(myQueue);
myQueue = nil;

此外,Apple Documentation表示

  

由于Grand Central Dispatch管理着您提供的任务与运行这些任务的线程之间的关系,因此通常应避免从任务代码中调用POSIX线程例程。如果确实由于某些原因需要调用它们,则应非常小心调用哪些例程

因此:如果您使用调度队列,请不要弄乱线程。