【问题标题】:fastest way to execute multiple methods all at the same time同时执行多个方法的最快方法
【发布时间】:2012-06-01 09:13:00
【问题描述】:

我有 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 对我来说是一个选择吗?怎么样?

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

【问题讨论】:

    标签: iphone objective-c ios asynchronous


    【解决方案1】:

    假设您不介意在后台顺序加载图像(而不是并行加载),一个简单的调度到后台队列运行 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 来运行它们。这将需要更多的努力来实施。如果同时处理多个大图像,还要注意内存使用情况。

    【讨论】:

    • 您可以将每个对 doSomethingAndReturn 的单独调用包装在其自己的 dispatch_async 中,以便它们都并行运行。要等待它们全部完成,您可以创建一个调度组。请参阅此处的文档:developer.apple.com/library/ios/documentation/General/…
    • 非常感谢..帮了我很多忙。
    • 不推荐 Low 甚至 Background 优先级。后台优先级队列限制了磁盘 I/O,因此加载图像不会很快。他想要最快的方式。
    • 谢谢!我有一个for循环决定任务,我将我的打印任务包装在dispatch_async中......如上回答,并同时进行了异步打印。我还在调度上方和for循环下方使用了@autorelease池。投票:)
    • @MikeWeller 你能建议与 nsoperation 相同的场景吗??
    【解决方案2】:

    你可以使用NSOperationQueue:

    NSOperationQueue 类管理一组 NSOperation 对象的执行。被添加到队列后,操作将保留在该队列中,直到它被显式取消或完成执行其任务。队列中的操作(但尚未执行)本身根据优先级和操作对象依赖关系进行组织,并相应地执行。一个应用程序可以创建多个操作队列并向其中的任何一个提交操作。

    example for a NSOperationQueue imeplementation

    GCD Queue:

    Grand Central Dispatch (GCD) 调度队列是执行任务的强大工具。调度队列允许您相对于调用者异步或同步地执行任意代码块。您可以使用调度队列来执行您过去在单独线程上执行的几乎所有任务。调度队列的优点是使用起来更简单,并且在执行这些任务时比相应的线程代码更有效率。

    example for a GCD Queue implementation

    【讨论】:

      【解决方案3】:

      您可以同时在处理器的另一个内核上执行该操作:

      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];
      

      如果您的处理器有四个内核,则每种方法都将在不同的内核上执行。

      【讨论】:

        【解决方案4】:

        我知道如何解决,但尚未测试。我正在从我遇到并解决的其他几个问题中得出解决方案:

        • NSNull 插入到NSMutableArray 作为占位符。
        • dispatch_async繁重的工作并替换NSMutableArray中的相应条目(使用@synchronized关键字锁定NSMutableArray
        • 同样在dispatch async 函数中,将函数分派回主队列以更新视图。

        【讨论】:

        • 感谢您的回复!一旦我触摸我的 Mac,就会尝试解决这个问题。
        【解决方案5】:

        我只是将其作为一个练习:对每个 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;
        }
        

        编辑:第二个想法:连续剧不是必需的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-24
          相关资源
          最近更新 更多