im正在开发一个应用,该应用使用一些框架通过openGL绘制3D人员。这个框架要求我从完全相同的线程中调用draw()
方法。
因此,我创建了一个串行DispatchQueue,并在其中启动了CADisplayLink,以60FPS的速度调用draw()
。我必须从这个确切的线程中调用其他几种方法,例如start()
和stop()
。这使队列成为我的理想解决方案。
您可能知道DispathQueue不能保证在同一线程上执行每个任务。这对我来说压力很大,因为它可能会破坏我的应用程序。
我真的不喜欢创建NSThread并在其上实现自己的队列的想法。
有什么方法可以将DispatchQueue绑定到确切的线程?也许可以绑定NSOperationQueue?
答案 0 :(得分:1)
在向应用程序添加并发性时,分派队列提供了一些优于线程的优点。最直接的好处是工作队列编程模型的简单性。使用线程,您必须为要执行的工作以及线程本身的创建和管理编写代码。调度队列使您可以专注于实际要执行的工作,而不必担心线程的创建和管理。而是由系统为您处理所有线程的创建和管理。优点是该系统比任何单个应用程序都能够更有效地管理线程。系统可以根据可用资源和当前系统状况动态扩展线程数量。此外,与您自己创建线程相比,系统通常能够更快地开始运行任务。
简单来说,您要么使用调度队列,简单地创建它们并向他们发送工作,要么使用NSThread
和NSRunLoop
s,创建它们,进行设置,发送工作给他们,并可能阻止他们。
详细信息:
创作:
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线程例程。如果确实由于某些原因需要调用它们,则应非常小心调用哪些例程
因此:如果您使用调度队列,请不要弄乱线程。