所以第一个问题是dispatch_async
如何确定使用哪个线程?只是随机挑选它?我需要做一些解析和核心数据的东西,所以我不想阻止UI线程并使用dispatch_async
,但之后我发送NSURLRequest
来获取更多数据,回调永远不会调用(可能是因为线程已经死了)。
那么制作它的好方法是什么?我无法使用
sendAsynchronousRequest:queue:completionHandler:
因为部署操作系统是4.现在我只是在
中发送请求dispatch_async(dispatch_get_main_queue(), ^{
});
位于dispatch_async(myQueue)
块内,它执行所有解析并保存到核心数据。但它对我来说似乎不对,我的意思是应该有一种方法来使用dispatch_async并告诉它不要杀掉它,对吗?因为使用同步请求不是一种选择。
答案 0 :(得分:12)
所以第一个问题是dispatch_async如何确定使用哪个线程?
使用GCD时不应该考虑线程。这些都是幕后处理的。您认为在队列中,您将传递给dispatch_async
以及要执行的块。 GCD队列会对一个线程进行映射,但您不必担心幕后发生的事情--GCD会为您处理所有这些事情。
至于你认为的代码看起来与此相似:
dispatch_async(myQueue, ^{
// Do some stuff off the main queue
dispatch_async(dispatch_get_main_queue(), ^{
// Do something with the UI
});
});
根本没有没有错误。您不必担心发送到myQueue
的块运行的线程可能会被终止。队列将保持不变,直到块完成运行。您在原始调度中调度到主队列的事实很好 - 主队列上的工作将很愉快地运行。
我想你也在问为什么在异步调度中使用NSURLRequest
时你会看到它不会调用回调。那将是因为它紧密耦合到当前的运行循环,如果你当前在后台线程(你的myQueue
将运行),那么该运行循环将不再运行,直到另一个块被放置在队列上。所以你的回调永远不会运行。
我鼓励你去阅读更多关于GCD以及async vs sync实际意味着什么,因为我觉得你可能还没有完全理解它。我回答了类似的问题here。
答案 1 :(得分:3)
在块中使用sendAsynchronousRequest:...
时,块将在异步请求回调被触发之前终止。
由于您已经在后台线程中,如何使用该线程中的同步方法 来获取数据 - +[NSURLRequest sendSynchronousRequest:returningResponse:error:]
,甚至更简单,+[NSData dataWithContentsOfURL:]
。
您可以在后台线程上运行的块中调用这些,并且在调用完成之前块不会继续。然后,您可以通过回调主队列来更新UI:
dispatch_async(yourQueue, ^{
// Do some stuff
NSData * fetchedData = [NSData dataWithContentsOfURL: someURL];
// Do some more stuff with the data
dispatch_async(dispatch_get_main_queue(), ^{
// Do some stuff on the main queue
}
});
答案 2 :(得分:0)
你是对的,问题是该线程已经死了,因为NSURLConnection在其生命周期内不会让它保持活着状态。连接将在返回时被丢弃。 你可以用一些黑魔法明确地保持线程活着;)并在你完成后释放线程。在这种情况下,通过在成功或出错时将_isFinishedLoading设置为true。
因此,在这种情况下,使用块时不关心线程是不正确的,因为NSURLConnection并不真正兼容。然而,块非常有用,因为框架会根据底层硬件和可用资源为您选择最佳线程。
NSURLConnection* connection = [NSURLConnection connectionWithRequest:urlRequest delegate:self];
[connection start];
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
_isFinishedLoading = NO;
while (!_isFinishedLoading)
{
[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}