Wednesday, 11 September 2013

Best way to pass data objects to Grand Central Dispatch Task

Best way to pass data objects to Grand Central Dispatch Task

Question: What is the preferred/best/accepted practice for passing data
(beyond primitives) to a background task using Grand Central Dispatch
(GCD)?
What concerns me with objective C blocks is this: Variables accessed by
the block are copied to the block data structure on the heap so that the
block can access them later. Copied pointer references could mean multiple
threads are accessing the same object.
I'm still fairly new to objective C and iOS but I'm not new threads (C++,
Java, C, C#).
Code set #1 (Primitive Copy from scope)
//Primitive int
int taskIdBlock = self->taskNumber;
//declare a block that takes in an ID and sleep time.
void (^runTask)(int taskId, int sleepTime);
//Create and assign the block
runTask = ^void(int taskId, int sleepTime)
{
NSLog(@"Running Task: %d", taskId);
// wait for x seconds before completing this method
[NSThread sleepForTimeInterval:sleepTime];
//update the main UI
//tell the main thread we are finished with this task.
dispatch_async(dispatch_get_main_queue(), ^
{
NSLog(@"Completed Task %d",taskId);
});
};
//Get the global concurrent dispatch queue and launch a few tasks
dispatch_queue_t globalConcurrentQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//TASK #1
//increment the task number and log
NSLog(@"Create Task Number %d", ++taskIdBlock);
//dispatch the task to the global queue.
dispatch_async(globalConcurrentQueue, ^{
runTask(taskIdBlock,5);
});
//TASK #2
//increment the task number and log
NSLog(@"Create Task Number %d", ++taskIdBlock);
//dispatch the task to the global queue.
dispatch_async(globalConcurrentQueue, ^{
runTask(taskIdBlock,3);
});
Output:
Create Task Number 1
Create Task Number 2
Running Task: 1
Running Task: 2
Completed Task 2
Completed Task 1
Code set #2 (Object Reference Copy from scope)
//Integer Object
NSInteger *taskIdBlock = &(self->taskNumber);
//declare a block that takes in an ID and sleep time.
void (^runTask)(int taskId, int sleepTime);
//Create and assign the block
runTask = ^void(int taskId, int sleepTime)
{
NSLog(@"Running Task: %d", taskId);
// wait for x seconds before completing this method
[NSThread sleepForTimeInterval:sleepTime];
//update the main UI
//tell the main thread we are finished with this task.
dispatch_async(dispatch_get_main_queue(), ^
{
NSLog(@"Completed Task %d",taskId);
});
};
//Get the global concurrent dispatch queue and launch a few tasks
dispatch_queue_t globalConcurrentQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//TASK #1
//increment the task number and log
NSLog(@"Create Task Number %d", ++(*taskIdBlock));
//dispatch the task to the global queue.
dispatch_async(globalConcurrentQueue, ^{
runTask(*taskIdBlock,5);
});
//TASK #2
//increment the task number and log
NSLog(@"Create Task Number %d", ++(*taskIdBlock));
//dispatch the task to the global queue.
dispatch_async(globalConcurrentQueue, ^{
runTask(*taskIdBlock,3);
});
Output:
Create Task Number 1
Running Task: 2
Create Task Number 2
Running Task: 2
Completed Task 2
Completed Task 2
Notice the 1st line in each piece of code. Primitive int to Object
NSinteger. I would have like to seen something like this:
dispatch_async(globalConcurrentQueue,runTask(*taskIdBlock,3));
However this does not compile. I can only see this getting more difficult
in the future so best to get a solid example down first. Thanks in
advance.

No comments:

Post a Comment