设置(dispatch_get_main_queue()、^ {…});等到做了什么?

时间:2022-05-15 21:00:06

I have a scenario in my app, where I want to do some time consuming task which consists of some data processing as well as UI update, in a method. My method looks like this,

我在我的应用程序中有一个场景,我想做一些耗时的任务,包括一些数据处理和UI更新,在一个方法中。我的方法是这样的,

- (void)doCalculationsAndUpdateUIs {

    // DATA PROCESSING 1
    // UI UPDATE 1

    // DATA PROCESSING 2
    // UI UPDATE 2

    // DATA PROCESSING 3
    // UI UPDATE 3
} 

As it is time consuming I wanted to do the data processing on the background thread, using,

由于这很耗时,我想在后台线程上进行数据处理,使用,

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{

But as both data processing and UI updates are in the same method, I wanted to move only the UI updates in main thread using,

但是由于数据处理和UI更新都使用相同的方法,所以我只想在主线程中移动UI更新,

dispatch_async(dispatch_get_main_queue(), ^{

Finally my method looks like this,

最后我的方法是这样的,

- (void)doCalculationsAndUpdateUIs {

    // DATA PROCESSING 1 
    dispatch_async(dispatch_get_main_queue(), ^{
        // UI UPDATE 1
    });

    /* I expect the control to come here after UI UPDATE 1 */

    // DATA PROCESSING 2
    dispatch_async(dispatch_get_main_queue(), ^{
        // UI UPDATE 2
    });

    /* I expect the control to come here after UI UPDATE 2 */

    // DATA PROCESSING 3
    dispatch_async(dispatch_get_main_queue(), ^{
        // UI UPDATE 3
    });
}

Does this really work? Is this really a good practice? What is the best way to achieve this?

这是否真的有效吗?这真的是一个很好的练习吗?达到这一目标的最佳方式是什么?

P.S. All these three operations are interrelated to each other.

另外,这三个操作都是相互关联的。


EDIT: Sorry guys. I have missed a line in the above code. My actual code looks like this.

编辑:对不起。我在上面的代码中漏掉了一行。我的实际代码是这样的。

- (void)doCalculationsAndUpdateUIs {

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // DATA PROCESSING 1 
        dispatch_async(dispatch_get_main_queue(), ^{
            // UI UPDATE 1
        });

        /* I expect the control to come here after UI UPDATE 1 */

        // DATA PROCESSING 2
        dispatch_async(dispatch_get_main_queue(), ^{
            // UI UPDATE 2
        });

        /* I expect the control to come here after UI UPDATE 2 */

        // DATA PROCESSING 3
        dispatch_async(dispatch_get_main_queue(), ^{
            // UI UPDATE 3
        });
    });
}

Once again, I really apologize for the confusion.

再次,我真的为我的困惑道歉。

7 个解决方案

#1


95  

No it doesn't wait and the way you are doing it in that sample is not good practice.

不,它不需要等待,你在样本中的做法不是很好的实践。

dispatch_async is always asynchronous. It's just that you are enqueueing all the UI blocks to the same queue so the different blocks will run in sequence but parallel with your data processing code.

设置都是异步的。只是将所有UI块排队到相同的队列中,这样不同的块将按顺序运行,但与数据处理代码并行。

If you want the update to wait you can use dispatch_sync instead.

如果希望更新等待,可以使用dispatch_sync。

// This will wait to finish
dispatch_sync(dispatch_get_main_queue(), ^{
    // Update the UI on the main thread.
});

Another approach would be to nest enqueueing the block. I wouldn't recommend it for multiple levels though.

另一种方法是嵌套对块进行排队。但我不建议在多个层次上使用它。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // Background work

    dispatch_async(dispatch_get_main_queue(), ^{
        // Update UI

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            // Background work

            dispatch_async(dispatch_get_main_queue(), ^{
                // Update UI
            });
        });
    });
});

If you need the UI updated to wait then you should use the synchronous versions. It's quite okay to have a background thread wait for the main thread. UI updates should be very quick.

如果需要更新UI以等待,那么应该使用同步版本。后台线程等待主线程是可以的。UI更新应该非常快。

#2


10  

You have to put your main queue dispatching in the block that runs the computation. For example (here I create a dispatch queue and don't use a global one):

您必须将主队列调度放在运行计算的块中。例如(这里我创建了一个调度队列,但不使用全局队列):

dispatch_queue_t queue = dispatch_queue_create("com.example.MyQueue", NULL);
dispatch_async(queue, ^{
  // Do some computation here.

  // Update UI after computation.
  dispatch_async(dispatch_get_main_queue(), ^{
    // Update the UI on the main thread.
  });
});

Of course, if you create a queue don't forget to dispatch_release if you're targeting an iOS version before 6.0.

当然,如果创建队列,如果目标是6.0之前的iOS版本,请不要忘记dispatch_release。

#3


8  

Your proposed doCalculationsAndUpdateUIs does data processing and dispatches UI updates to the main queue. I presume that you have dispatched doCalculationsAndUpdateUIs to a background queue when you first called it.

您建议的doCalculationsAndUpdateUIs进行数据处理并将UI更新发送到主队列。我假定您在第一次调用doCalculationsAndUpdateUIs时已经将它发送到后台队列。

While technically fine, that's a little fragile, contingent upon your remembering to dispatch it to the background every time you call it: I would, instead, suggest that you do your dispatch to the background and dispatch back to the main queue from within the same method, as it makes the logic unambiguous and more robust, etc.

虽然技术很好,有点脆弱,视你的记忆分派到背景你每次叫它:我想,相反,表明你分派的背景和派遣回主队列中相同的方法,使逻辑明确的和更健壮,等等。

Thus it might look like:

因此,它可能看起来是:

- (void)doCalculationsAndUpdateUIs {

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{

        // DATA PROCESSING 1 

        dispatch_async(dispatch_get_main_queue(), ^{
            // UI UPDATION 1
        });

        /* I expect the control to come here after UI UPDATION 1 */

        // DATA PROCESSING 2

        dispatch_async(dispatch_get_main_queue(), ^{
            // UI UPDATION 2
        });

        /* I expect the control to come here after UI UPDATION 2 */

        // DATA PROCESSING 3

        dispatch_async(dispatch_get_main_queue(), ^{
            // UI UPDATION 3
        });
    });
}

In terms of whether you dispatch your UI updates asynchronously with dispatch_async (where the background process will not wait for the UI update) or synchronously with dispatch_sync (where it will wait for the UI update), the question is why would you want to do it synchronously: Do you really want to slow down the background process as it waits for the UI update, or would you like the background process to carry on while the UI update takes place.

而言,你是否异步分派UI更新和设置(后台进程不会等待UI更新)或同步dispatch_sync(它将等待UI更新),问题是为什么要做同步:你真的想慢下来的后台进程等待UI更新,或者你想后台进程进行,而UI更新。

Generally you would dispatch the UI update asynchronously with dispatch_async as you've used in your original question. Yes, there certainly are special circumstances where you need to dispatch code synchronously (e.g. you're synchronizing the updates to some class property by performing all updates to it on the main queue), but more often than not, you just dispatch the UI update asynchronously and carry on. Dispatching code synchronously can cause problems (e.g. deadlocks) if done sloppily, so my general counsel is that you should probably only dispatch UI updates synchronously if there is some compelling need to do so, otherwise you should design your solution so you can dispatch them asynchronously.

通常,您将使用dispatch_async异步分派UI更新,就像您在最初的问题中使用的那样。是的,确实有一些特殊情况需要同步发送代码(例如,通过在主队列上执行对某个类属性的所有更新来同步更新),但通常情况下,您只需异步发送UI更新并继续执行。同步分派代码可能会导致问题(例如死锁),因此我的建议是,如果需要同步分派UI更新,那么应该只同步分派,否则应该设计解决方案,以便异步分派。


In answer to your question as to whether this is the "best way to achieve this", it's hard for us to say without knowing more about the business problem being solved. For example, if you might be calling this doCalculationsAndUpdateUIs multiple times, I might be inclined to use my own serial queue rather than a concurrent global queue, in order to ensure that these don't step over each other. Or if you might need the ability to cancel this doCalculationsAndUpdateUIs when the user dismisses the scene or calls the method again, then I might be inclined to use a operation queue which offers cancelation capabilities. It depends entirely upon what you're trying to achieve.

在回答你的问题“这是否是实现这一目标的最佳途径”时,如果我们不了解正在解决的业务问题,我们就很难说清。例如,如果您可能多次调用这个doCalculationsAndUpdateUIs,我可能倾向于使用我自己的串行队列,而不是并发的全局队列,以确保它们不会相互影响。或者,如果当用户取消场景或再次调用方法时,您可能需要取消这个doCalculationsAndUpdateUIs,那么我可能倾向于使用提供取消功能的操作队列。这完全取决于你想要达到的目标。

But, in general, the pattern of asynchronously dispatching a complicated task to a background queue and then asynchronously dispatching the UI update back to the main queue is very common.

但是,一般来说,异步地将复杂的任务分派到后台队列,然后异步地将UI更新发送回主队列的模式非常常见。

#4


2  

If you want to run a single independent queued operation and you’re not concerned with other concurrent operations, you can use the global concurrent queue:

如果您想运行一个独立的队列操作,而不关心其他并发操作,您可以使用全局并发队列:

dispatch_queue_t globalConcurrentQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

This will return a concurrent queue with the given priority as outlined in the documentation:

这将返回一个具有文档中列出的给定优先级的并发队列:

DISPATCH_QUEUE_PRIORITY_HIGH Items dispatched to the queue will run at high priority, i.e. the queue will be scheduled for execution before any default priority or low priority queue.

发送到队列的DISPATCH_QUEUE_PRIORITY_HIGH项将以高优先级运行,也就是说,队列将被安排在任何默认优先级或低优先级队列之前执行。

DISPATCH_QUEUE_PRIORITY_DEFAULT Items dispatched to the queue will run at the default priority, i.e. the queue will be scheduled for execution after all high priority queues have been scheduled, but before any low priority queues have been scheduled.

分派给队列的DISPATCH_QUEUE_PRIORITY_DEFAULT项将以默认优先级运行,即队列将在所有高优先级队列都被调度之后,但在任何低优先级队列被调度之前被调度。

DISPATCH_QUEUE_PRIORITY_LOW Items dispatched to the queue will run at low priority, i.e. the queue will be scheduled for execution after all default priority and high priority queues have been scheduled.

分派给队列的DISPATCH_QUEUE_PRIORITY_LOW项将以低优先级运行,也就是说,在所有默认优先级和高优先级队列被调度之后,队列将被安排执行。

DISPATCH_QUEUE_PRIORITY_BACKGROUND Items dispatched to the queue will run at background priority, i.e. the queue will be scheduled for execution after all higher priority queues have been scheduled and the system will run items on this queue on a thread with background status as per setpriority(2) (i.e. disk I/O is throttled and the thread’s scheduling priority is set to lowest value).

DISPATCH_QUEUE_PRIORITY_BACKGROUND物品派遣到队列将运行在背景优先,即队列将定于执行毕竟较高优先级队列已经预定,系统将一个线程上运行此队列上的项目每setpriority(2)背景地位(如磁盘I / O是压制和线程的调度优先级设置为最小值)。

#5


1  

No, it won't wait.

不,它不会等待。

You could use performSelectorOnMainThread:withObject:waitUntilDone:.

您可以使用performSelectorOnMainThread:withObject:waitUntilDone:。

#6


1  

dispatch_queue_t queue = dispatch_queue_create("com.example.MyQueue", NULL);
dispatch_async(queue, ^{
  // Do some computation here.

  // Update UI after computation.
  dispatch_async(dispatch_get_main_queue(), ^{
    // Update the UI on the main thread.
  });
});

#7


0  

OK, there are two ways of doing that:

好的,有两种方法:

// GLOBAL_CONCURRENT_QUEUE


- (void)doCalculationsAndUpdateUIsWith_GlobalQUEUE 
{
    dispatch_queue_t globalConcurrentQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(globalConcurrentQ, ^{

       // DATA PROCESSING 1
       sleep(1);
       NSLog(@"Hello world chekpoint 1");
       dispatch_sync(dispatch_get_main_queue(), ^{
           // UI UPDATION 1
           sleep(1);
           NSLog(@"Hello world chekpoint 2");
       });

        /* the control to come here after UI UPDATION 1 */
        sleep(1);
        NSLog(@"Hello world chekpoint 3");
        // DATA PROCESSING 2

        dispatch_sync(dispatch_get_main_queue(), ^{
            // UI UPDATION 2
            sleep(1);
            NSLog(@"Hello world chekpoint 4");
        });

        /* the control to come here after UI UPDATION 2 */
        sleep(1);
        NSLog(@"Hello world chekpoint 5");
        // DATA PROCESSING 3

        dispatch_sync(dispatch_get_main_queue(), ^{
            // UI UPDATION 3
            sleep(1);
            NSLog(@"Hello world chekpoint 6");
        });
   });
}



// SERIAL QUEUE
- (void)doCalculationsAndUpdateUIsWith_GlobalQUEUE 
{

    dispatch_queue_t serialQ = dispatch_queue_create("com.example.MyQueue", NULL);
    dispatch_async(serialQ, ^{

       // DATA PROCESSING 1
       sleep(1);
       NSLog(@"Hello world chekpoint 1");

       dispatch_sync(dispatch_get_main_queue(), ^{
           // UI UPDATION 1
           sleep(1);
           NSLog(@"Hello world chekpoint 2");
       });


       sleep(1);
       NSLog(@"Hello world chekpoint 3");
       // DATA PROCESSING 2

       dispatch_sync(dispatch_get_main_queue(), ^{
           // UI UPDATION 2
           sleep(1);
           NSLog(@"Hello world chekpoint 4");
       });  
   });
}

#1


95  

No it doesn't wait and the way you are doing it in that sample is not good practice.

不,它不需要等待,你在样本中的做法不是很好的实践。

dispatch_async is always asynchronous. It's just that you are enqueueing all the UI blocks to the same queue so the different blocks will run in sequence but parallel with your data processing code.

设置都是异步的。只是将所有UI块排队到相同的队列中,这样不同的块将按顺序运行,但与数据处理代码并行。

If you want the update to wait you can use dispatch_sync instead.

如果希望更新等待,可以使用dispatch_sync。

// This will wait to finish
dispatch_sync(dispatch_get_main_queue(), ^{
    // Update the UI on the main thread.
});

Another approach would be to nest enqueueing the block. I wouldn't recommend it for multiple levels though.

另一种方法是嵌套对块进行排队。但我不建议在多个层次上使用它。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // Background work

    dispatch_async(dispatch_get_main_queue(), ^{
        // Update UI

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            // Background work

            dispatch_async(dispatch_get_main_queue(), ^{
                // Update UI
            });
        });
    });
});

If you need the UI updated to wait then you should use the synchronous versions. It's quite okay to have a background thread wait for the main thread. UI updates should be very quick.

如果需要更新UI以等待,那么应该使用同步版本。后台线程等待主线程是可以的。UI更新应该非常快。

#2


10  

You have to put your main queue dispatching in the block that runs the computation. For example (here I create a dispatch queue and don't use a global one):

您必须将主队列调度放在运行计算的块中。例如(这里我创建了一个调度队列,但不使用全局队列):

dispatch_queue_t queue = dispatch_queue_create("com.example.MyQueue", NULL);
dispatch_async(queue, ^{
  // Do some computation here.

  // Update UI after computation.
  dispatch_async(dispatch_get_main_queue(), ^{
    // Update the UI on the main thread.
  });
});

Of course, if you create a queue don't forget to dispatch_release if you're targeting an iOS version before 6.0.

当然,如果创建队列,如果目标是6.0之前的iOS版本,请不要忘记dispatch_release。

#3


8  

Your proposed doCalculationsAndUpdateUIs does data processing and dispatches UI updates to the main queue. I presume that you have dispatched doCalculationsAndUpdateUIs to a background queue when you first called it.

您建议的doCalculationsAndUpdateUIs进行数据处理并将UI更新发送到主队列。我假定您在第一次调用doCalculationsAndUpdateUIs时已经将它发送到后台队列。

While technically fine, that's a little fragile, contingent upon your remembering to dispatch it to the background every time you call it: I would, instead, suggest that you do your dispatch to the background and dispatch back to the main queue from within the same method, as it makes the logic unambiguous and more robust, etc.

虽然技术很好,有点脆弱,视你的记忆分派到背景你每次叫它:我想,相反,表明你分派的背景和派遣回主队列中相同的方法,使逻辑明确的和更健壮,等等。

Thus it might look like:

因此,它可能看起来是:

- (void)doCalculationsAndUpdateUIs {

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{

        // DATA PROCESSING 1 

        dispatch_async(dispatch_get_main_queue(), ^{
            // UI UPDATION 1
        });

        /* I expect the control to come here after UI UPDATION 1 */

        // DATA PROCESSING 2

        dispatch_async(dispatch_get_main_queue(), ^{
            // UI UPDATION 2
        });

        /* I expect the control to come here after UI UPDATION 2 */

        // DATA PROCESSING 3

        dispatch_async(dispatch_get_main_queue(), ^{
            // UI UPDATION 3
        });
    });
}

In terms of whether you dispatch your UI updates asynchronously with dispatch_async (where the background process will not wait for the UI update) or synchronously with dispatch_sync (where it will wait for the UI update), the question is why would you want to do it synchronously: Do you really want to slow down the background process as it waits for the UI update, or would you like the background process to carry on while the UI update takes place.

而言,你是否异步分派UI更新和设置(后台进程不会等待UI更新)或同步dispatch_sync(它将等待UI更新),问题是为什么要做同步:你真的想慢下来的后台进程等待UI更新,或者你想后台进程进行,而UI更新。

Generally you would dispatch the UI update asynchronously with dispatch_async as you've used in your original question. Yes, there certainly are special circumstances where you need to dispatch code synchronously (e.g. you're synchronizing the updates to some class property by performing all updates to it on the main queue), but more often than not, you just dispatch the UI update asynchronously and carry on. Dispatching code synchronously can cause problems (e.g. deadlocks) if done sloppily, so my general counsel is that you should probably only dispatch UI updates synchronously if there is some compelling need to do so, otherwise you should design your solution so you can dispatch them asynchronously.

通常,您将使用dispatch_async异步分派UI更新,就像您在最初的问题中使用的那样。是的,确实有一些特殊情况需要同步发送代码(例如,通过在主队列上执行对某个类属性的所有更新来同步更新),但通常情况下,您只需异步发送UI更新并继续执行。同步分派代码可能会导致问题(例如死锁),因此我的建议是,如果需要同步分派UI更新,那么应该只同步分派,否则应该设计解决方案,以便异步分派。


In answer to your question as to whether this is the "best way to achieve this", it's hard for us to say without knowing more about the business problem being solved. For example, if you might be calling this doCalculationsAndUpdateUIs multiple times, I might be inclined to use my own serial queue rather than a concurrent global queue, in order to ensure that these don't step over each other. Or if you might need the ability to cancel this doCalculationsAndUpdateUIs when the user dismisses the scene or calls the method again, then I might be inclined to use a operation queue which offers cancelation capabilities. It depends entirely upon what you're trying to achieve.

在回答你的问题“这是否是实现这一目标的最佳途径”时,如果我们不了解正在解决的业务问题,我们就很难说清。例如,如果您可能多次调用这个doCalculationsAndUpdateUIs,我可能倾向于使用我自己的串行队列,而不是并发的全局队列,以确保它们不会相互影响。或者,如果当用户取消场景或再次调用方法时,您可能需要取消这个doCalculationsAndUpdateUIs,那么我可能倾向于使用提供取消功能的操作队列。这完全取决于你想要达到的目标。

But, in general, the pattern of asynchronously dispatching a complicated task to a background queue and then asynchronously dispatching the UI update back to the main queue is very common.

但是,一般来说,异步地将复杂的任务分派到后台队列,然后异步地将UI更新发送回主队列的模式非常常见。

#4


2  

If you want to run a single independent queued operation and you’re not concerned with other concurrent operations, you can use the global concurrent queue:

如果您想运行一个独立的队列操作,而不关心其他并发操作,您可以使用全局并发队列:

dispatch_queue_t globalConcurrentQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

This will return a concurrent queue with the given priority as outlined in the documentation:

这将返回一个具有文档中列出的给定优先级的并发队列:

DISPATCH_QUEUE_PRIORITY_HIGH Items dispatched to the queue will run at high priority, i.e. the queue will be scheduled for execution before any default priority or low priority queue.

发送到队列的DISPATCH_QUEUE_PRIORITY_HIGH项将以高优先级运行,也就是说,队列将被安排在任何默认优先级或低优先级队列之前执行。

DISPATCH_QUEUE_PRIORITY_DEFAULT Items dispatched to the queue will run at the default priority, i.e. the queue will be scheduled for execution after all high priority queues have been scheduled, but before any low priority queues have been scheduled.

分派给队列的DISPATCH_QUEUE_PRIORITY_DEFAULT项将以默认优先级运行,即队列将在所有高优先级队列都被调度之后,但在任何低优先级队列被调度之前被调度。

DISPATCH_QUEUE_PRIORITY_LOW Items dispatched to the queue will run at low priority, i.e. the queue will be scheduled for execution after all default priority and high priority queues have been scheduled.

分派给队列的DISPATCH_QUEUE_PRIORITY_LOW项将以低优先级运行,也就是说,在所有默认优先级和高优先级队列被调度之后,队列将被安排执行。

DISPATCH_QUEUE_PRIORITY_BACKGROUND Items dispatched to the queue will run at background priority, i.e. the queue will be scheduled for execution after all higher priority queues have been scheduled and the system will run items on this queue on a thread with background status as per setpriority(2) (i.e. disk I/O is throttled and the thread’s scheduling priority is set to lowest value).

DISPATCH_QUEUE_PRIORITY_BACKGROUND物品派遣到队列将运行在背景优先,即队列将定于执行毕竟较高优先级队列已经预定,系统将一个线程上运行此队列上的项目每setpriority(2)背景地位(如磁盘I / O是压制和线程的调度优先级设置为最小值)。

#5


1  

No, it won't wait.

不,它不会等待。

You could use performSelectorOnMainThread:withObject:waitUntilDone:.

您可以使用performSelectorOnMainThread:withObject:waitUntilDone:。

#6


1  

dispatch_queue_t queue = dispatch_queue_create("com.example.MyQueue", NULL);
dispatch_async(queue, ^{
  // Do some computation here.

  // Update UI after computation.
  dispatch_async(dispatch_get_main_queue(), ^{
    // Update the UI on the main thread.
  });
});

#7


0  

OK, there are two ways of doing that:

好的,有两种方法:

// GLOBAL_CONCURRENT_QUEUE


- (void)doCalculationsAndUpdateUIsWith_GlobalQUEUE 
{
    dispatch_queue_t globalConcurrentQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(globalConcurrentQ, ^{

       // DATA PROCESSING 1
       sleep(1);
       NSLog(@"Hello world chekpoint 1");
       dispatch_sync(dispatch_get_main_queue(), ^{
           // UI UPDATION 1
           sleep(1);
           NSLog(@"Hello world chekpoint 2");
       });

        /* the control to come here after UI UPDATION 1 */
        sleep(1);
        NSLog(@"Hello world chekpoint 3");
        // DATA PROCESSING 2

        dispatch_sync(dispatch_get_main_queue(), ^{
            // UI UPDATION 2
            sleep(1);
            NSLog(@"Hello world chekpoint 4");
        });

        /* the control to come here after UI UPDATION 2 */
        sleep(1);
        NSLog(@"Hello world chekpoint 5");
        // DATA PROCESSING 3

        dispatch_sync(dispatch_get_main_queue(), ^{
            // UI UPDATION 3
            sleep(1);
            NSLog(@"Hello world chekpoint 6");
        });
   });
}



// SERIAL QUEUE
- (void)doCalculationsAndUpdateUIsWith_GlobalQUEUE 
{

    dispatch_queue_t serialQ = dispatch_queue_create("com.example.MyQueue", NULL);
    dispatch_async(serialQ, ^{

       // DATA PROCESSING 1
       sleep(1);
       NSLog(@"Hello world chekpoint 1");

       dispatch_sync(dispatch_get_main_queue(), ^{
           // UI UPDATION 1
           sleep(1);
           NSLog(@"Hello world chekpoint 2");
       });


       sleep(1);
       NSLog(@"Hello world chekpoint 3");
       // DATA PROCESSING 2

       dispatch_sync(dispatch_get_main_queue(), ^{
           // UI UPDATION 2
           sleep(1);
           NSLog(@"Hello world chekpoint 4");
       });  
   });
}