线程,优先级和放弃

我最近在iOS上成为线程好奇。 请向我指出你将要采取的方向,以在现代iOS设备上实现(如果可能)以下…谢谢!

用户正在input文字,每隔几秒钟说一个字。

我不时想启动DifficultProcess来做一些语义处理。 总之,我想我需要做四件事情:

  • 从main启动DifficultProcess
  • 如果DifficultProcess完成,从它得到一个消息到同一个主
  • 如果我想,从主要放弃,摆脱,困难的过程
  • 最后的优先问题:DifficultProcess必须比主要或用户input具有更低的优先级,我想DifficultProcess真的真的优先; 这甚至有可能吗?

从本质上来说,现代(2011年)(1月下旬)iOS中对A,B,C使用的调用是什么? 我不在乎爸爸的方法! 甚至可能以任何方式“D”?

我想这是四个想法!

所以特别是我想发送一个消息,换句话说,在运行的后台进程中调用一个例程(如果需要的话,可以closures正在运行的后台进程,或者改变它的运行模式等)。

(对于1997年之前出生的人,你会认识到这是典型的“投机加工”范式。)

感谢任何人可以打扰这个指针!

我会build议使用NSOperation和NSOperationQueue来pipe理你需要能够任意取消的后台活动。

NSOperation的取消和NSOperationQueue的取消AllOperations是方法来看待。

为了从后台获取消息到主线程,dispatch_async-to-main-thread-queue技术很好。 你可以把它和你的NSOperation的委托协议结合起来,把你想要发送的消息编码。

例如

@protocol MyOperationDelegate - (void) operationStarted:(MyOperation *)operation; - (void) makingProgressOnItem:(id)anItem otherInterestingItem:(NSDictionary *)otherItem remainingCount:(NSUInteger)count; - (void) operationWillFinish:(MyOperation *)operation; @end @interface MyOperation id <MyOperationDelegate> delegate; @end @implementation MyOperation ... - (void) cancel { [super cancel]; // Tell the delegate we're about to finish (due to cancellation). dispatch_sync (dispatch_get_main_queue(), ^{ [self.delegate operationWillFinish:self]; }); } - (void) main { // Check for cancellation if (self.isCancelled) return; // Starting dispatch_sync (dispatch_get_main_queue(), ^{ [self.delegate operationStarted:self]; }); if (self.isCancelled) return; // Another cancel check // Send async progress messages periodically while doing some work while (workNotDone) { // Do some work ... dispatch_async (dispatch_get_main_queue(), ^{ [self.delegate makingProgressOnItem:foo otherInterestingItem:bar remainingCount:baz]; }); if (self.isCancelled) return; } // About to finish if (!self.isCancelled) { dispatch_sync (dispatch_get_main_queue(), ^{ [self.delegate operationWillFinish:self]; }); } } @end 

KVO不适合线程间通信; 在发生键值变化的线程上收到观察结果。 所以,如果你的后台线程改变一个值,你的后台线程将接收到关于它的KVO。 可能不是你想要的。

爷爷的-performSelectorOnMainThread:withObject:waitUntilDone:继续是一个很好的方式来获取消息回主线程。 限制是你的消息只能访问一个基于对象的参数。 dispatch_async到主线程没有这个限制。

如果要从后台线程向主线程发出asynchronous(或同步)NSNotification,则需要使用-performSelectorOnMainThread。

 NSNotification *note = [NSNotification notificationWithName:FinishedABunchOfWorkNotification object:self userInfo:nil]; [[NSNotificationCenter defaultCenter] performSelectorOnMainThread:@selector(postNotification:) withObject:note waitUntilDone:YES]; 

我build议使用dispatch_async到全局低优先级队列(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0))。

取消是棘手的,但。 除了“分块”并检查每个块的标志之外,没有一个好的通用机制来取消后台工作。

为了让消息返回dispatch_async回到主队列。 如果你正好斜视,你可以把dispatch_async当作演员模型中的“发送消息”。

(编辑),如果你需要在后台序列化的东西,做一个私人队列,并将其目标设置为全球低优先级iirc。

我引用爸爸的方法(自iPhone 2以来一直存在)的风险

- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg

只要您记住您必须在您作为select器传递的方法中创build一个新的自动释放池,并在方法结束时将其耗尽,那么这很容易且十分简单。 除此之外,做任何你喜欢的 – 除了触​​摸UIKit。 它不是线程安全的,所以任何UI更改都必须通过

 - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait 

或KVO触发器。 关键值观察将是您的后台线程与主线程沟通工作完成的好方法。

 - (void)myBackgroundThreadMethod { NSAutoreleasePool *threadPool = [[NSAutoreleasePool alloc] init]; // my time-consuming processing here [threadPool drain]; } 

为了更精确地控制线程,你需要看看NSThread。 线程编程指南详细列出了所有细节 – 如果您通过NSThread创build线程,则可以控制线程何时启动。 该文件确实build议离开线程单独并让它终止 – 但显示如何终止它。 一种方法是- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait

NSThread文档也说“单独留下优先权”。 你可以设置线程优先级

 + (BOOL)setThreadPriority:(double)priority 

但我从来不知道这是必要的,调度程序足够聪明,以保持UI响应。