菜鸟教程小白 发表于 2022-12-12 09:44:42

ios - 在 dispatch_async 和 dispatch_sysnc 中更新 UI 的区别


                                            <p><p>假设我有一个名为 session 的 NSURLSession,我想在 downloadTaskWithRequest 中更新我的 UI。现在,情况 1 和情况 2 会发生什么:</p>

<p><strong>案例 1:</strong>(dispatch_async)</p>

<pre><code>NSURLSession *session = ;

NSURLSessionDownloadTask *task= [session downloadTaskWithRequest:request
completionHandler:^(NSURL *localFile, NSURLResponse *response, NSError *error){
    dispatch_async(dispatch_get_main_queue(), ^{
                  // UI Update   
                                             });
}];
</code></pre>

<p><strong>案例 2:</strong>(使用 dispatch_sync)</p>

<pre><code>NSURLSessionDownloadTask *task= [session downloadTaskWithRequest:request
completionHandler:^(NSURL *localFile, NSURLResponse *response, NSError *error){
    dispatch_sync(dispatch_get_main_queue(), ^{
                  // UI Update   
                                             });
}];
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p><strong>tl;dr</strong> 第二种情况将等待 UI 更新完成。首先是更快。</p>

<p><strong>详细</strong></p>

<p><code>dispathc_sync</code> 阻止当前队列上的执行,直到分派(dispatch)的任务完成。所以,如果主队列上发生了大事,案例二将需要很长时间才能完成。但是,当完成处理程序完成其工作时(例如,如果您在 UI 更新调度后执行某些操作),您确定 UI 已经更新。
   此外,如果由于某种未知原因您将配置 <code>session</code> 以在主队列上分派(dispatch)完成 block ,则在第二种情况下您将遇到死锁。这是因为主队列是串行的,这意味着它一次只执行一个任务 - 所以完成处理程序将等待 UI 更新完成,直到完成处理程序没有完成,UI 更新才会开始。</p>

<p><code>dispatch_async</code> 不会阻塞执行流程。这意味着,您不会以任何方式陷入死锁,并且完成 block 执行时间将不取决于 UI 更新持续时间。但是,即使完成处理程序完成,您也不知道 UI 更新是否完成。
   但是,如果您的 <code>completionHandler</code> 分派(dispatch)到主队列,更新的 UI 将仅在 <code>completionHandler</code> 完成后执行。 </p>

<p><strong>分割</strong>
案例二:</p>

<pre><code>completionHandler:^(NSURL *localFile, NSURLResponse *response, NSError *error){
    //Some code
    //1
    dispatch_sync(dispatch_get_main_queue(), ^{
                  //2
                  // UI Update   
                  //3
                                             });
    //Some code
    //4
}];
</code></pre>

<p>到达<code>//1</code>,到达<code>//2</code>,到达<code>//3</code>,到达<code>//4</code> .保证执行顺序。无论如何——不管是这样还是根本不执行。</p>

<p>案例一:</p>

<pre><code>completionHandler:^(NSURL *localFile, NSURLResponse *response, NSError *error){
    //Some code
    //1
    dispatch_async(dispatch_get_main_queue(), ^{
                  //2
                  // UI Update   
                  //3
                                             });
    //Some code
    //4
}];
</code></pre>

<p>到达 <code>//1</code>。保证。在那之后变种可能。
到达 <code>//2</code>,到达 <code>//4</code>,到达 <code>//3</code>。
或者
到达 <code>//4</code>,到达 <code>//2</code>,到达 <code>//3</code>
或者
到达 <code>//2</code>,到达 <code>//3</code>,到达 <code>//4</code>。</p>

<p>如果 <code>completionBlock</code> 在主队列上调度,则第二个将始终如此。</p>

<p>如果有什么不清楚的地方欢迎提问</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 在 dispatch_async 和 dispatch_sysnc 中更新 UI 的区别,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/33809977/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/33809977/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 在 dispatch_async 和 dispatch_sysnc 中更新 UI 的区别