DispatchQueue 绑定到确切的线程

DoN*_*1cK 1 multithreading grand-central-dispatch ios

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

所以我创建了一个串行 DispatchQueue 并在其中启动 CADisplayLink,draw()以 60FPS调用。我必须从这个确切的线程调用其他一些方法,例如start()stop()。这使队列对我来说是完美的解决方案。

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

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

有没有办法将 DispatchQueue 绑定到精确的线程?也许可以绑定 NSOperationQueue ?

gog*_*gog 6

正如Apple 文档所说:

在向应用程序添加并发性时,调度队列比线程提供了几个优势。最直接的优点是工作队列编程模型的简单性。对于线程,您必须为要执行的工作以及线程本身的创建和管理编写代码。调度队列让你专注于你真正想要执行的工作,而不必担心线程的创建和管理。相反,系统会为您处理所有线程的创建和管理。优点是系统能够比任何单个应用程序更有效地管理线程。系统可以根据可用资源和当前系统条件动态调整线程数。此外,

简而言之,您要么使用调度队列,简单地创建它们并向它们发送工作,要么使用NSThreads 和NSRunLoops,创建它们,设置它们,向它们发送工作,并可能停止它们。

详细:

NSThread / NSRunLoop

创建:

self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadMainRoutine) object:nil];
[self.thread start];
Run Code Online (Sandbox Code Playgroud)

开始/管理:

- (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;
}
Run Code Online (Sandbox Code Playgroud)

添加要对其执行的工作:

[self performSelector:@selector(mySelector:) onThread:myThread withObject:myObject waitUntilDone:YES];
Run Code Online (Sandbox Code Playgroud)

关掉:

- (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;
}
Run Code Online (Sandbox Code Playgroud)

调度队列

创建:

dispatch_queue_t myQueue = dispatch_queue_create("My Queue", DISPATCH_QUEUE_SERIAL);
Run Code Online (Sandbox Code Playgroud)

开始:

dispatch_resume(myQueue);
Run Code Online (Sandbox Code Playgroud)

添加要对其执行的工作:

dispatch_async(myQueue, (void)^ {
    // put the work into this block
});
Run Code Online (Sandbox Code Playgroud)

关掉:

dispatch_suspend(myQueue);
myQueue = nil;
Run Code Online (Sandbox Code Playgroud)

此外,苹果文档

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

所以:如果你使用调度队列,不要搞乱线程。