线程,优先级和放弃
我最近在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响应。