我以前从未使用过后台线程。我当前在主线程上运行一个耗时的计算,该计算将数据输出附加到TERecord。我的工作流程基本上是:
运行漫长的过程… 更新GUI… 运行漫长的过程... 更新GUI… 等等。
在代码产生(字符串)输出的几个地方,我通过调用如下所示的'addToRecord'方法来更新UI:
-(void)addToRecord:(NSString*)passedStr:(BOOL)updateUI
{
NSRange endRange;
// add the passed text...
endRange.location = [[theOutputView textStorage] length];
endRange.length = 0;
[theOutputView replaceCharactersInRange:endRange withString:passedStr];
if(updateUI) // immediate GUI update needed...
{
// scroll window contents to BOTTOM of page...
endRange = NSMakeRange([[theOutputView string] length],0);
[theOutputView scrollRangeToVisible:endRange];
[theOutputView display];
}
}
当然,在完成工作的同时,我的整个UI仍然无响应,直到流程完成为止。我知道我应该对以前从未使用过的后台线程进行繁重的工作。我在创建如下所示的后台线程时发现了部分问题:
-(IBAction)readUserInput:(id)sender
{
// irrelevant code snipped for brevity
if([self checkForErrors] == NO)
{
[runButton setEnabled:NO];
[self performSelectorInBackground:@selector(runWorkThread) withObject:nil];
}
}
-(void)runWorkThread
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
[self runLongProcess];
[pool drain];
}
但是我只是不明白每次代码遇到我的'addToRecord'方法时如何调用主线程,然后如何将控制权返回给后台线程? 另一种可能是从我的'addToRecord'方法中删除updateUI代码,而让主线程在计时器上每秒大约调用一次此代码?
任何建议和示例代码将不胜感激。谢谢!
答案 0 :(得分:0)
可以使用 Dispatch 框架(也称为GCD)代替使用performSelectorInBackground
,这是处理并发工作的首选方式。 Dispatch已经设置了可以使用的后台线程池。要切换线程,您可以像这样调用dispatch_async()
:
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
// :
// Do your background work here
// :
dispatch_async(dispatch_get_main_queue(), ^{
// :
// Now you are back in the main thread
// :
});
});
第一个参数是队列标识符,由dispatch_get_global_queue()
提供给您,该标识符返回一个“工人”队列,或者dispatch_get_main_queue()
返回一个主队列。最后一个参数是在所选队列上执行的代码块。
使用dispatch_get_global_queue()
请求并发队列时,请指定服务质量,该质量确定代码相对于其他工作的优先级。请参阅文档以获取更多信息和可能的值。