2012-06-01 52 views
6

我有4个方法,每个方法在方法返回前需要一两秒钟的时间,这些方法返回UIImage,我需要这些图像以最快的方式显示。最快的方式同时执行多个方法

-(NSMutableArray*)prepareImages{ 
    UIImage *imageToModifyUsingUIImageCategory; 

    NSMutableArray *imageArray = [[NSMutableArray alloc]initWithObjects: 
    [imageToModifyUsingUIImageCategory doSomethingAndReturn1], 
    [imageToModifyUsingUIImageCategory doSomethingAndReturn2], 
    [imageToModifyUsingUIImageCategory doSomethingAndReturn3], 
    [imageToModifyUsingUIImageCategory doSomethingAndReturn4],nil];  
    return imageArray; 
} 

在上面的方法结束时,我将从该数组中得到4个图像。每个“doSomethingAndReturn”方法需要一秒或两秒钟,这意味着我的prepareImages方法将约5秒钟完成执行。太长了吧?

我的问题是,有什么可以通过其他方式来完成所有这些更快? GCD是我的选择吗?怎么样?

任何帮助将不胜感激。谢谢!

回答

15

假设你不介意在后台(而不是平行)加载图像顺序,一个简单的派遣背景队列运行prepareImages将这样的伎俩:

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... 
    }); 
}); 

这会将图像加载到低优先级的背景队列中,然后在完成后再发送回主线程。

如果你想保持更低的优先级,你可以使用DISPATCH_QUEUE_PRIORITY_BACKGROUND,尽管这只适用于iOS 4.3及更高版本。在这种情况下,您应该检查来自dispatch_get_global_queue的返回值,如果返回0,则可以回退到其他优先级之一。

如果要并行加载每个图像,您应该将doSomethingAndReturn方法转换为NSOperation子类,并使用NSOperationQueue来运行它们全部。这需要更多的努力才能实施。如果一次处理多个大图像,请注意内存使用情况。

+0

谢谢,我正在考虑将doSomethingAndReturn方法转换为NSOperation,但我很怀疑尝试一下。但我会尽力做出努力,因为你只是推我:)顺便说一句,使用gcd与doSomethingAndReturn而不是NSOperation?我想gcd更优雅,但你认为我可以用它做到吗?谢谢! – janusbalatbat

+2

您可以将每个单独的调用包装在自己的dispatch_async中,以使它们全部并行运行。要等待他们完成,您可以创建一个调度组。请参阅此处的文档:http://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW25 –

+0

非常感谢非常感谢...帮了我很多。 –

1

我有一个想法如何解决,但尚未测试。我从我遇到并解决其他一些问题绘图解决方案:

  • 插入NSNullNSMutableArray用作占位符。
  • dispatch_async繁重的工作并替换NSMutableArray相应的条目(使用@synchronized关键字锁定NSMutableArray
  • 同样在dispatch async功能,调度回到主队列中的函数来更新视图。
+0

感谢您的回应!将尝试解决,只要我碰我的Mac。 – janusbalatbat

1

你可以使用一个NSOperationQueue

的NSOperationQueue类调节一组的NSOperation对象的执行。在添加到队列后,操作将保留在该队列中,直到它被明确取消或完成其任务。队列中的操作(但尚未执行)本身根据优先级和操作间对象依赖性进行组织,并相应执行。应用程序可能会创建多个操作队列并将操作提交给它们中的任何一个。

example for a NSOperationQueue imeplementation

GCD Queue

大中央调度(GCD)调度队列是用于执行任务的有力工具。调度队列让你可以与调用者异步或同步地执行任意代码块。您可以使用分派队列来执行几乎所有用于在单独的线程上执行的任务。调度队列的优点是它们比相应的线程代码更简单,更有效地执行这些任务。

example for a GCD Queue implementation

1

您可以在同一时间对做你的处理器的另一个核心是试图执行:

​​

如果您的处理器有四个核心每种方法将在一个不同的核心执行。

0

我只是将它作为练习:对每个doSomethingAndReturn使用GCD并发Q,并使用串行q来监视回调数。当回调次数等于doSomethingAndReturn(s)的次数时,则返回prepareImages数组。

我创建了测试该概念的代码。

-(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; 
} 

编辑:第2个想法:串行是没有必要的。