我正在使用NSOperation
和绘图:
我有一个主线程创建我的NSOperation
子类,然后将其添加到NSOperationQueue
。
我的NSOperation
执行了一些繁重的处理,它打算在main()方法中循环几分钟,不断处理一些工作,但是现在我只有一个带睡眠的while()循环(1 )内部,设置为5次左右(用于测试)。
产生此NSOperation
的主(原始)线程负责绘制视图并更新UI。
我打算让NSOperation线程使用通知来告诉主线程它已经完成了一些处理,此时每次通过while()循环时发送一次通知(即;一次)一秒钟,因为它只是在做睡眠(1))。主线程(视图)注册接收这些通知。
通知立即进入主线程,看起来是异步的,看起来很好。似乎两个线程都按预期运行......即 - 同时运行。 (我使用NSLog()来粗略检查每个线程何时发送和接收通知)。
当视图收到通知并调用其处理程序方法时,我只是递增一个整数变量,并尝试将其绘制到视图中(当然是一个字符串)。在测试中,drawRect中的代码:将此整数(作为字符串)绘制到屏幕上就好了。
然而:这是我的问题(对不起,这需要花一点时间才能到达):当主线程(视图)收到来自NSOperation的通知时,它会更新此测试整数并调用[self setNeedsDisplay]。但是,在NSOperation完成之前,视图不会重绘!我期望NSOperation作为一个单独的线程,无法阻止主线程的事件循环,但看起来这就是正在发生的事情。当NSOperation完成并且其main()返回时,视图最终会立即重新绘制。
也许我没有正确使用NSOperation
。我在“非并发”模式下使用它,但尽管我的理解是这仍然产生一个新线程并允许异步处理。
如果您希望看到某些代码,请与我们联系。
答案 0 :(得分:10)
在主线程上没有执行响应您的通知而执行的观察者中的方法。
因此,在该方法中,您可以使用performSelectorOnMainThread:withObject:waitUntilDone:
强制另一个方法在主线程上运行。
例如:
<强> MyOperation.m 强>
- (void)main {
for (int i = 1; i <= 5; i++) {
sleep(1);
[[NSNotificationCenter defaultCenter] postNotificationName:@"GTCNotification" object:[NSNumber numberWithInteger:i]];
}
}
<强> MyViewController.m 强>
- (void)setupOperation {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myNotificationResponse:) name:@"GTCNotification" object:nil];
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
MyOperation *myOp = [[MyOperation alloc] init];
[opQueue addOperation:myOp];
[myOp release];
[opQueue release];
}
- (void)myNotificationResponse:(NSNotification*)note {
NSNumber *count = [note object];
[self performSelectorOnMainThread:@selector(updateView:) withObject:count waitUntilDone:YES];
}
- (void)updateView:(NSNumber*)count {
countLabel.text = count.stringValue;
}
答案 1 :(得分:0)
大多数人都知道任何与显示相关的任务都必须在主线程上完成。但是,作为其直接结果,还必须在主线程上修改可能影响绘图的Cocoa绑定属性的任何更改(因为KVO触发器将在触发它们的线程上处理)。这对大多数人来说是一个惊喜:特别是,从主线程以外的线程调用[self setNeedsDisplay]是不安全的。
如gerry所述,您的NSNotification不会在主线程上处理,它会在发送它的线程上处理。因此,在NSNotification处理程序中,如果它们与显示相关或者它们影响Cocoa绑定,则必须将命令发送回主线程。 @performSelector工作,但是有了队列,我发现了一种更简单,更易读的方法:
[ [ NSOperationQueue mainQueue] addOperationWithBlock:^(void) {
/* Your main-thread code here */ }];
它避免了辅助辅助函数的定义,其唯一目的是从主线程调用。 mainQueue仅在&gt; 10.6中定义。