NSOperation阻止UI绘画?

我在使用NSOperation和绘图之后有一些build议:

我有一个主线程创build我的NSOperation子类,然后将其添加到NSOperationQueue

我的NSOperation做了一些繁重的处理,它打算在main()方法中循环几分钟,不断地处理一些工作,但是现在我只是有一个while()循环,里面有一个sleep(1),它被设置为5次左右(testing)。

产生这个NSOperation的主(原始)线程负责绘制到视图和更新UI。

我打算让NSOperation线程使用一个通知来告诉主线程它已经完成了一些处理,现在这个通知每一次发送一次,通过它的while()循环发送一次(也就是每秒一次,因为它只是在睡觉(1))。 主线程(视图),注册以接收这些通知。

通知立即通过主线程,看起来asynchronous,看起来很好。 看来,两个线程按预期运行…这是 – 同时。 (我使用NSLog()只是大致检查每个线程发送和接收通知)。

当视图接收到一个通知,并且它的处理方法被调用时,我只需递增一个整型variables,然后试着将其绘制到视图中(作为一个当然的string)。 在testing中,drawRect中的代码:将这个整数(作为string)绘制到屏幕上。

然而,这里是我的问题(对不起,需要一点时间来到这里):当主线程(视图)从NSOperation接收到通知时,它更新此testing整数并调用[self setNeedsDisplay]。 但是,直到NSOperation完成之后,视图才会重绘! 我期望NSOperation,作为一个单独的线程,将无法阻止主线程的事件循环,但似乎这是发生了什么事情。 当NSOperation完成并且它的main()返回时,视图最终重新绘制自己。

也许我没有正确使用NSOperation 。 我在“非并发”模式下使用它,但尽pipe名字我的理解是,这仍然产生一个新的线程,并允许asynchronous处理。

任何帮助或build议非常感谢,如果你想看到一些代码只是让我知道。

主线程上没有执行观察者中响应您的通知而执行的方法。

因此,在该方法中,可以使用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; } 

大多数人都知道,任何与显示相关的任务都必须在主线程上完成。 但是,直接的结果是,对可能影响绘图的Cocoa绑定属性的任何更改也必须在主线程上修改(因为KVO触发器将在触发它们的线程上处理)。 这对大多数人来说是一个惊喜:特别是从主线程以外的线程调用[self setNeedsDisplay]是不安全的。

正如gerry所提到的,你的NSNotification不在主线程上处理,而是在它发送的线程上处理。 因此,在您的NSNotification处理程序中,如果它们与显示相关或者它们影响cocoa绑定,则必须将您的命令发送回主线程。 @performSelector工作,但与队列,我发现一个更容易和更可读的方法:

 [ [ NSOperationQueue mainQueue] addOperationWithBlock:^(void) { /* Your main-thread code here */ }]; 

它避免了辅助函数的定义,它的唯一目的是从主线程调用。 mainQueue仅在> 10.6中定义。