The fastest way to execute multiple methods at once

I have 4 methods, each method takes a second or two, before the method returns, these methods will return UIImage, I need these images to display the fastest way I can.

-(NSMutableArray*)prepareImages{ UIImage *imageToModifyUsingUIImageCategory; NSMutableArray *imageArray = [[NSMutableArray alloc]initWithObjects: [imageToModifyUsingUIImageCategory doSomethingAndReturn1], [imageToModifyUsingUIImageCategory doSomethingAndReturn2], [imageToModifyUsingUIImageCategory doSomethingAndReturn3], [imageToModifyUsingUIImageCategory doSomethingAndReturn4],nil]; return imageArray; } 

at the end of the above method, I will have 4 images from this array. each doSomethingAndReturn method takes a second or two, so my prepareImages method prepareImages finish in about 5 seconds. too long huh

my QUESTION: what could be another way to accomplish all this faster? Is this a GCD option for me? as?

Any help would be greatly appreciated. thanks!

+6
source share
5 answers

Assuming you don't mind loading images sequentially in the background (and not parallel), just sending them to the background to start prepareImages will do the trick:

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ NSArray *images = [self prepareImages]; // now send the result back to the main thread so we can do // UIKit stuff dispatch_async(dispatch_get_main_queue(), ^{ // set the images on your UIImageViews here... }); }); 

This will upload the images to the low priority queue and then go back to the main thread after it finishes.

If you want to keep this even lower priority, you can use DISPATCH_QUEUE_PRIORITY_BACKGROUND , although this is only available in iOS 4.3 and later. You should check the return value from dispatch_get_global_queue in this case, and if it returns 0, you can step back from one of the other priorities.

If you want to load each image in parallel, you should probably turn your doSomethingAndReturn methods into subclasses of NSOperation and use NSOperationQueue to run them. This will require a little more effort. Also be careful when using memory if you are processing several large images at once.

+15
source

I have an idea how to solve, but not yet verified. I draw a solution from several other problems that I encountered and solved:

  • Insert NSNull into NSMutableArray as placeholders.
  • dispatch_async hard work and replace the corresponding entry in NSMutableArray (use the @synchronized keyword to block NSMutableArray )
  • Also, in the dispatch async function, send the function to update the view back to the main queue.
+1
source

you can use NSOperationQueue :

The NSOperationQueue class controls the execution of a set of NSOperation objects. After adding to the queue, the operation remains in this queue until it is explicitly canceled or completes its task. Operations in the queue (but not yet performed) are themselves organized in accordance with priority levels and dependencies between operational objects and are performed accordingly. An application can create multiple queues of operations and send operations to any of them.

example for implementing NSOperationQueue

or GCD Queue :

Grand Central Dispatch (GCD) Dispatch Queues are a powerful tool for completing tasks. Send queues allow arbitrary blocks of code to be executed either asynchronously or synchronously with respect to the caller. You can use send queues to perform almost all the tasks that you used for individual threads. The advantage of sending queues is that they are easier to use and much more efficient in performing these tasks than the corresponding threading code.

example for implementing a GCD queue

+1
source

You can run the same time on another core of your processor to try:

 NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil]; NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil]; NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil]; NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil]; 

If your processor has four cores, each method will run on a different core.

+1
source

I just do it as an exercise: use a GCD in parallel with Q for each doSomethingAndReturn and use serial q to control the number of callbacks. When the number of callbacks is equal to the number of doSomethingAndReturn (s), then we return the prepareImages array.

I created code to test the concept.

 -(NSString *)doSomethingAndReturn1 { for (int i=0; i<30; i++) { NSLog(@"soSomethingAndReturn1 i: %i", i); } return @"soSomethingAndReturn1"; } -(NSString *)doSomethingAndReturn2 { for (int i=0; i<10; i++) { NSLog(@"soSomethingAndReturn2 i: %i", i); } return @"soSomethingAndReturn2"; } -(NSString *)doSomethingAndReturn3 { for (int i=0; i<20; i++) { NSLog(@"soSomethingAndReturn3 i: %i", i); } return @"soSomethingAndReturn3"; } -(void)addToArray:(NSString *)str { [asyncArray addObject:str]; NSLog(@"asyncArray: %@", asyncArray); } - (IBAction)buttonMultitasksPressed:(id)sender { dispatch_queue_t serialdQueue; serialdQueue = dispatch_queue_create("com.mydomain.testbed.multimethods", NULL); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self addToArray:[self doSomethingAndReturn1]]; }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self addToArray:[self doSomethingAndReturn2]]; }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self addToArray:[self doSomethingAndReturn3]]; }); dispatch_sync(serialdQueue, ^{ while (!([asyncArray count] == 3)) { NSLog(@"not there yet count: %i", [asyncArray count]); } }); NSLog(@"end of dispatch_sync serialQueue"); // return asyncArray; } 

Edit: 2nd thought: The series is not needed.

0
source

Source: https://habr.com/ru/post/917163/


All Articles