如何在NSThread中等待,直到iOS发生某些事件?

在iOS中发生某些事件之前,如何在NSThread内等待?

例如,我们创建了一个NSThread并启动了一个线程循环。 在线程循环内部,有条件检查消息队列是否有任何消息。 如果有消息,那么它将调用相应的方法来执行某些操作,否则它应该等到消息队列填充新消息。

是否有任何API或方法可以等到某个事件发生?

For Example NSThread *thread = [NSThread alloc]....@selector(threadLoop) - (void)threadLoop { // Expecting some API or method that wait until some messages pushed into the message queue if (...) { } } 

任何帮助应该得到赞赏。

您可以使用NSCondition。 我在ViewController中附加了示例代码“ready-for-test”

 @interface ViewController () @property (strong, nonatomic) NSCondition *condition; @property (strong, nonatomic) NSThread *aThread; // use this property to indicate that you want to lock _aThread @property (nonatomic) BOOL lock; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // start with the thread locked, update the boolean var self.lock = YES; // create the NSCondition instance self.condition = [[NSCondition alloc]init]; // create the thread and start self.aThread = [[NSThread alloc] initWithTarget:self selector:@selector(threadLoop) object:nil]; [self.aThread start]; } -(void)threadLoop { while([[NSThread currentThread] isCancelled] == NO) { [self.condition lock]; while(self.lock) { NSLog(@"Will Wait"); [self.condition wait]; // the "did wait" will be printed only when you have signaled the condition change in the sendNewEvent method NSLog(@"Did Wait"); } // read your event from your event queue ... // lock the condition again self.lock = YES; [self.condition unlock]; } } - (IBAction)sendNewEvent:(id)sender { [self.condition lock]; // put the event in the queue ... self.lock = NO; [self.condition signal]; [self.condition unlock]; } 

您可以使用运行循环源 。 在本质上:

1)在辅助工作线程上创建并安装运行循环源,并以某种方式将其与工作线程运行循环引用一起传递给其他管理线程,该线程将向此发送消息:

  CFRunLoopSourceContext context = {0, self, NULL, NULL, NULL, NULL, NULL, &RunLoopSourceScheduleRoutine, RunLoopSourceCancelRoutine, RunLoopSourcePerformRoutine}; CFRunLoopSourceRef runLoopSource = CFRunLoopSourceCreate(NULL, 0, &context); CFRunLoopRef runLoop = CFRunLoopGetCurrent(); CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopDefaultMode); // Pass runLoopSource and runLoop to managing thread 

这里有上面提到的自定义例程 – 您有责任提供它们:

  RunLoopSourceScheduleRoutine - called when you install run loop source (more precisely, when you call CFRunLoopAddSource) RunLoopSourceCancelRoutine - called when you remove run loop source (more precisely, when you call CFRunLoopSourceInvalidate) RunLoopSourcePerformRoutine - called when run loop source was signaled (received a message from manager thread) and this is a place where you should perform a job 

2)在工作线程上,启动通常的运行循环,类似于:

  BOOL done = NO; do { int result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, YES); done = (result == kCFRunLoopRunStopped) || (result == kCFRunLoopRunFinished); } while (!done); 

3)现在,在管理线程时,您可以在需要时向先前接收的运行循环源发送信号(发送消息)(并在它处于睡眠状态时唤醒这些线程的运行循环):

  CFRunLoopSourceSignal(runLoopSource); CFRunLoopWakeUp(workerThreadRunLoop); 

Apple的指南中提供了更多详细信息。

您可以使用信号量。 看下面的例子,逻辑非常简单。 在我的例子中,块在后台执行,我的主线程等待信号量的发送信号继续。 主要区别在于我的情况是线程等待是主线程,但信号量逻辑在这里,我认为你可以很容易地适应你的情况。

 //create the semaphore dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); [objectManager.HTTPClient deletePath:[address addressURL] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { //some code here dispatch_semaphore_signal(semaphore); }failure:^(AFHTTPRequestOperation *operation, NSError *error) { //some other code here dispatch_semaphore_signal(semaphore); }]; //holds the thread until the dispatch_semaphore_signal(semaphore); is send while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]]; }