繁体   English   中英

dispatch_async和异步请求的问题

[英]issue with dispatch_async and async request

所以第一个问题是dispatch_async如何确定使用哪个线程? 只是随机挑选它? 我需要做一些解析和核心数据的东西,所以我不想阻止UI线程并使用dispatch_async ,但之后我发送NSURLRequest来获取更多数据并且永远不会调用回调(可能因为线程已经死)。

那么制作它的好方法是什么? 我不能用

sendAsynchronousRequest:queue:completionHandler: 

因为部署操作系统是4.现在我只是发送请求

dispatch_async(dispatch_get_main_queue(), ^{
});

它位于dispatch_async(myQueue)块中,它执行所有解析并保存到核心数据。 但它对我来说似乎不对,我的意思是应该有一种方法来使用dispatch_async并告诉它不要杀掉它,对吗? 因为使用同步请求不是一种选择。

所以第一个问题是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实际意味着什么,因为我觉得你可能还没有完全理解它。 在这里回答了类似的问题。

当您在块中使用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
    }
});

你是对的,问题是线程已经死了,因为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]];
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM