这是一个两部分的问题。希望有人能给出完整的答案。
NSOperation
s 是强大的对象。它们可以是两种不同的类型:非并发或并发。
第一种是同步运行的。您可以通过将非并发操作添加到NSOperationQueue
. 后者为您创建一个线程。结果在于以并发方式运行该操作。唯一需要注意的是此类操作的生命周期。当它的main
方法完成时,它就会从队列中移除。当您处理异步 API 时,这可能是一个问题。
现在,并发操作呢?来自苹果文档
如果要实现并发操作(即相对于调用线程异步运行的操作),则必须编写额外的代码来异步启动操作。例如,您可能会生成一个单独的线程、调用异步系统函数或执行其他任何操作来确保 start 方法启动任务并立即返回,并且很可能在任务完成之前返回。
这对我来说几乎是很清楚的。它们异步运行。但是您必须采取适当的措施来确保他们这样做。
我不清楚的是以下内容。医生说:
注意:在 OS X v10.6 中,操作队列会忽略 isConcurrent 返回的值,并始终从单独的线程调用操作的 start 方法。
它的真正含义是什么?如果我在 a 中添加并发操作会发生什么NSOperationQueue
?
然后,在这篇文章并发操作中,并发操作用于通过NSURLConnection
(以异步形式)下载一些 HTTP 内容。操作是并发的并包含在特定队列中。
UrlDownloaderOperation * operation = [UrlDownloaderOperation urlDownloaderWithUrlString:url];
[_queue addOperation:operation];
由于NSURLConnection
需要一个循环来运行,作者start
在主线程中分流了该方法(所以我想将操作添加到它产生的队列中)。以这种方式,主运行循环可以调用包含在操作中的委托。
- (void)start
{
if (![NSThread isMainThread])
{
[self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:NO];
return;
}
[self willChangeValueForKey:@"isExecuting"];
_isExecuting = YES;
[self didChangeValueForKey:@"isExecuting"];
NSURLRequest * request = [NSURLRequest requestWithURL:_url];
_connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self];
if (_connection == nil)
[self finish];
}
- (BOOL)isConcurrent
{
return YES;
}
// delegate method here...
我的问题如下。这个线程安全吗?运行循环侦听源,但调用的方法在后台线程中调用。我错了吗?
编辑
根据 Dave Dribin 提供的代码,我自己完成了一些测试(参见1)。正如您所写,我注意到NSURLConnection
在主线程中调用了 的回调。
好的,但现在我仍然很困惑。我会试着解释我的怀疑。
为什么在并发操作中包含在主线程中调用其回调的异步模式?将方法分流start
到主线程允许在主线程中执行回调,那么队列和操作呢?我在哪里可以利用 GCD 提供的线程机制?
希望这很清楚。