如何等待NSThread,直到iOS中发生某些事件?
问题描述:
如何在NSThread内部等待,直到iOS中发生某些事件?如何等待NSThread,直到iOS中发生某些事件?
例如,我们创建了一个NSThread,并开始一个线程循环。在线程循环中,有条件检查消息队列是否有任何消息。如果有消息,那么它会调用相应的方法来执行一些操作,否则它应该等到消息队列填充新消息。
是否有任何可用的API或方法来等待某些事件发生?
For Example
NSThread *thread = [NSThread alloc][email protected](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];
}
答
您可以使用信号量。看下面的例子,逻辑非常简单。我的例子,块在后台执行,我的主线程等待信号量的调度信号继续。主要区别在于我的情况线程等待是主线程,但信号逻辑在这里,我认为你可以很容易地适应你的情况。
//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]];
}
答
您可以使用run loop sources。从本质上说:
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的guide。
正是我在找的东西。非常简单,干净的例子。 –
非常好的例子 – ashokdy