14

我需要保证同一个线程在任意时间执行各种操作。首先线程需要初始化一个库,然后我希望线程休眠直到需要完成工作并且在用户输入时,我需要能够传递选择器或块以执行。

如何在初始化后将 NSRunLoop 设置为休眠?之后,我如何向运行循环发出信号以唤醒并做某事?

我已经尝试阅读 iOS 的线程编程指南,但我想避免将类设置为自定义输入类并使用更轻量级的东西,例如performSelector:onThread:

我可以设置一个从现在开始永远触发的计时器,这样运行循环就不会结束吗?

这基本上是我想要的伪代码:

// Initialization Code...

do {
    sleepUntilSignaled();
    doWorkSentToThisThread();
while (!done);

我将工作作为performSelector:onThread:消息发送到哪里。如果我可以向运行循环发送这样的块会更好:^{[someObj message]; [otherObj otherMsg];}但我会很高兴,performSelector因为我很确定无需太多额外的编码就可以实现。

谢谢!

4

3 回答 3

11

您的问题中包含所有必要的部分。你启动你的线程并让它运行它的runloop。如果你需要线程做一些事情,你可以performSelector:onThread:在主线程上使用它来做。

但是,您必须注意 runloop 的一件事:除非它具有输入源或附加了计时器,否则它不会运行。只需在运行循环中附加一个计时器,该计时器会在遥远的将来触发某个时间,然后一切就绪。

// Initialization code here

[NSTimer scheduledTimerWithTimeInterval: FLT_MAX
                                 target: self selector: @selector(doNothing:)
                               userInfo: nil repeats:YES];

NSRunLoop *rl = [NSRunLoop currentRunLoop];
do {
    [rl runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!done);

使用performSelector:onThread:withObject:您还可以将您的块传递给后台线程。您需要做的就是在某处编写一个方法,该方法将块作为参数并运行它:

@interface NSThread (sendBlockToBackground)
- (void) performBlock: (void (^)())block;
@end

@implementation NSThread (sendBlockToBackground)
- (void) performBlock: (void (^)())block;
{
    [self performSelector: @selector(runBlock:) 
                 onThread: self withObject: block waitUntilDone: NO];
}

- (void) runBlock: (void (^)())block;
{
    block();
}
@end

但也许你应该使用调度队列而不是所有这些。这需要更少的代码,并且可能还具有更少的开销:

dispatch_queue_t myQueue = dispatch_queue_create( "net.example.product.queue", NULL );
dispatch_async( myQueue, ^{
    // Initialization code here
} );

// Submit block:
dispatch_async( myQueue, ^{
    [someObject someMethod: someParameter];
} );

使用创建的调度队列dispatch_queue_create是一个串行队列 - 发送到它的所有块将按照它们到达的相同顺序执行,一个接一个。

于 2010-10-15T08:50:24.497 回答
2

考虑使用 NSConditionLock。它是为这样的任务而设计的。想象一下,您有一个包含数据的队列。第一个线程将数据添加到队列中,第二个线程等待数据并处理它。

id condLock = [[NSConditionLock alloc] initWithCondition:NO_DATA];

//First thread
while(true)
{
    [condLock lock];
    /* Add data to the queue. */
    [condLock unlockWithCondition:HAS_DATA];
}

//Second thread
while (true)
{
    [condLock lockWhenCondition:HAS_DATA];
    /* Remove data from the queue. */
    [condLock unlockWithCondition:(isEmpty ? NO_DATA : HAS_DATA)];

    // Process the data locally.
}
于 2011-12-23T01:05:09.513 回答
0

我认为您可以将NSInvocationOperation与 NSOperationQueue 一起使用。

于 2010-10-15T08:39:17.200 回答