Ios dispatch\u async和async请求出现问题
因此,第一个问题是Ios dispatch\u async和async请求出现问题,ios,multithreading,asynchronous,grand-central-dispatch,Ios,Multithreading,Asynchronous,Grand Central Dispatch,因此,第一个问题是dispatch\u async如何确定使用哪个线程?随便挑?我需要做一些解析和核心数据的工作,所以我不想阻塞UI线程并使用dispatch\u async,但在那之后,我发送一个NSURLRequest,以获取更多的数据,回调永远不会被调用(可能是因为线程已经死了) 那么什么是制作它的好方法呢?我不能用 sendAsynchronousRequest:queue:completionHandler: 因为部署操作系统是4。现在我只是把请求发送到内部 dispatch_as
dispatch\u async
如何确定使用哪个线程?随便挑?我需要做一些解析和核心数据的工作,所以我不想阻塞UI线程并使用dispatch\u async
,但在那之后,我发送一个NSURLRequest
,以获取更多的数据,回调永远不会被调用(可能是因为线程已经死了)
那么什么是制作它的好方法呢?我不能用
sendAsynchronousRequest:queue:completionHandler:
因为部署操作系统是4。现在我只是把请求发送到内部
dispatch_async(dispatch_get_main_queue(), ^{
});
它位于
dispatch\u async(myQueue)
块中,该块完成对核心数据的所有解析和保存。但对我来说这似乎并不正确,我的意思是应该有一种方法使用dispatch\u async并告诉它不要扼杀趋势,对吗?因为使用同步请求不是一个选项。当您在块内使用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
}
});
因此,第一个问题是dispatch_async如何确定使用哪个线程
在使用GCD时,不应该考虑线程。这些都是你在幕后处理的。您在队列中思考,这是您传递给dispatch\u 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的内容,以及异步与同步的实际含义,因为我觉得您可能还没有完全理解它。我回答了一个类似的问题。你是对的,问题是线程已经死了,因为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]];
}
但我担心的是(从GCD引用中)“函数在块完成之前不会返回。调用此函数并以当前队列为目标会导致死锁。”并且此代码将执行多次。我收到了一个带有20个ID的响应,然后我为每个ID发送了一个请求,所以如果服务器不可用,比如说呢?线程将被阻塞。。我习惯于认为使用任何同步请求都不是一个好主意,所以我的问题是,如果我创建了很多包含同步网络请求的dispatch\u async-s,那么我会耗尽线程吗?
dispatch\u async
!=新线程。一个新队列可能意味着一个新线程,但它可能不是。跟我重复:“我不必担心线程,GCD会为我处理它。”:-)。因此,基本上,如果您将async分派到同一队列上,那么这些队列将一个接一个地运行(除非它是并行队列)。有关这方面的更多信息,请参阅我在回答末尾链接的帖子。因此,可以肯定的是,在dispatch_async中调用同步请求完全可以吗?(除了不能取消的事实外)只要您没有将分派到与分派\u async
相同的队列上就可以了,这应该是相当明显的。同步意味着对dispatch\u sync
的调用在您分派的块完成之前不会返回,而在外部块返回=deadlock之前,该块无法运行。