1

我正在编写一个应用程序,它需要在另一个方法完成后运行一个方法。(常见的情况,对吧?)

我正在尝试实现链式方法。我想出的最好办法是打电话performSelector:withObject:afterDelay:。我只是不确定这是否是最好的方法。我研究了 Cocos2d 游戏引擎是如何实现它的CCSequence类的,但我不确定我是否理解它。

我怀疑块在这里会做得很好,除了我不确定如何将它们用作回调对象或其他什么。

我将如何实现一种运行方法的机制,一个接一个?(我愿意使用计时器或块,但我不知道在这种情况下我将如何使用块。)

编辑:

澄清一下,我正在尝试实现一个像 cocos2d 的CCSequence类这样的系统,它采用一些方法并按顺序“分派”它们。诸如动​​画之类的东西,运行需要的时间远不止一个时钟周期。

我不想阻塞主线程,也不想将方法硬编码给彼此。Cocos2d 有一个排序系统,我可以在其中将方法传递给队列并按顺序运行它们。

编辑2:

另外,我希望能够取消我的预定队列,所以我不确定 GCD 是否适合此。GCD 串行队列可以取消吗?

4

5 回答 5

7

您可以使用线程迁移技术

然后是一个有趣的任务,叫做GCD-Grand Central Dispatch

Grand Central Dispatch (GCD) 是 Apple Inc. 开发的一项技术,用于优化对具有多核处理器的系统和其他对称多处理系统的应用程序支持。它是基于线程池模式的任务并行实现。

GCD 的工作原理是允许程序中可以并行运行的特定任务排队等待执行,并根据处理资源的可用性,安排它们在任何可用的处理器内核上执行

调度队列是维护任务队列的对象,可以是匿名代码块或函数,并轮流执行这些任务。该库自动创建多个具有不同优先级的队列,这些队列同时执行多个任务,并根据操作环境选择要运行的最佳任务数量。库的客户端也可以创建任意数量的串行队列,它们按照提交的顺序执行任务,一次一个。因为串行队列一次只能运行一个任务,所以提交给队列的每个任务对于队列中的其他任务都是至关重要的,因此可以使用串行队列来代替对竞争资源的锁定。

调度队列相对于其他调度队列同时执行它们的任务。任务的序列化仅限于单个调度队列中的任务。

在您的情况下,您可以使用串行调度队列

当您希望任务以特定顺序执行时,串行队列很有用。串行队列一次只执行一个任务,并且总是从队列的头部拉取任务。您可以使用串行队列而不是锁来保护共享资源或可变数据结构。与锁不同,串行队列确保任务以可预测的顺序执行。只要您将任务异步提交到串行队列,队列就永远不会死锁。

与为您创建的并发队列不同,您必须显式创建和管理要使用的任何串行队列。您可以为您的应用程序创建任意数量的串行队列,但应避免仅将创建大量串行队列作为同时执行尽可能多的任务的手段。如果要同时执行大量任务,请将它们提交到全局并发队列之一。创建串行队列时,请尝试确定每个队列的用途,例如保护资源或同步应用程序的某些关键行为。

dispatch_queue_t queue;

queue = dispatch_queue_create("com.example.MyQueue", NULL);

此代码显示了创建自定义串行队列所需的步骤。dispatch_queue_create 函数有两个参数:队列名称和一组队列属性。调试器和性能工具显示队列名称以帮助您跟踪任务的执行方式。队列属性保留供将来使用,并且应该为 NULL。

Grand Central Dispatch 提供了一些功能,让您可以从应用程序访问几个常见的调度队列:

使用dispatch_get_current_queue函数进行调试或测试当前队列的身份。从块对象内部调用此函数会返回块被提交到的队列(并且它现在可能正在运行)。从块外部调用此函数会返回应用程序的默认并发队列。

使用dispatch_get_main_queue函数获取与应用程序主线程关联的串行调度队列。此队列是为 Cocoa 应用程序和调用 dispatch_main 函数或在主线程上配置运行循环(使用 CFRunLoopRef 类型或 NSRunLoop 对象)的应用程序自动创建的。

使用dispatch_get_global_queue函数来获取任何共享并发队列。

注意:您不需要保留或释放任何全局调度队列,包括并发调度队列或主调度队列。任何保留或释放队列的尝试都将被忽略。

来源:并发编程指南

于 2012-07-08T08:52:24.520 回答
6

使用串行 GCD 队列怎么样?

私有调度队列

串行队列(也称为私有调度队列)按添加到队列的顺序一次执行一项任务。当前正在执行的任务在由调度队列管理的不同线程上运行(可能因任务而异)。串行队列通常用于同步对特定资源的访问。您可以根据需要创建任意数量的串行队列,并且每个队列相对于所有其他队列同时运行。换句话说,如果您创建四个串行队列,每个队列一次只执行一个任务,但最多仍可以同时执行四个任务,每个队列一个。有关如何创建串行队列的信息,请参阅“创建串行调度队列”。</p>

来源

如果您希望在后台线程中处理所有消息,这将很有用。

于 2012-07-08T06:58:43.340 回答
2

有两个 performSelector 方法可以等待完成,无需猜测时间。

[self performSelector:<#(SEL)#> onThread:<#(NSThread *)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>];

[self performSelectorOnMainThread:<#(SEL)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>];
于 2012-07-08T06:57:29.143 回答
1

我终于找到了我要找的东西。完成块。简单地说,我会写一个这样的方法:

- (void) performSomeActionWithCompletion:(void (^)()) completion{

     [self someAction];

     if(completion()){
       completion(); 
     }

}

现在我可以这样调用我的方法:

[self performSomeActionWithCompletion:^{
  NSLog(@"All done! (Well, not the async stuff, but at any rate...)");
}];
于 2012-08-27T11:42:39.780 回答
1

听起来您想签出NSOperationQueue,NSOperationNSBlockOperationNSInvocationOperation。与 GCD 队列不同,anNSOperationQueue支持取消作业。

您可以创建自己的队列并将其最大并发操作计数设置为 1 以强制其串行执行操作。或者您可以设置操作之间的依赖关系以强制这些操作连续运行。

从并发编程指南中的操作队列一章开始。

于 2012-07-08T15:26:49.917 回答