1
 NSOperationQueue *queue = [NSOperationQueue new];
 NSInvocationOperation *operation;
 for(int k=0; k<[imageArray count]; k++)
 {
     operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadData:) object:[imageArray objectAtIndex:k]];
     [queue addOperation:operation];
     [operation release];
 }  

使用上面的代码我调用了loadData下载一些图像的方法。

-(void)loadData:(NSString*)newImage
{
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:newImage]];
    NSString* appSuppPath = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString* foofile = [appSuppPath stringByAppendingPathComponent:@"/PSDB"];


    NSString * str =[NSString stringWithFormat:@"%@/%d.jpeg",foofile,x];
    x++;
    [imageData writeToFile:str atomically:YES];
    [CATransaction commit];
}

图像已下载并保存。问题是小尺寸的图像被快速下载。例如,如果第 6 个图像是小尺寸图像,则它首先下载并保存为1.jpeg. 我怎样才能按订单制作。

4

2 回答 2

0

来自 NSOperationQueue文档

操作队列根据其优先级和准备情况执行其排队的操作对象。如果所有排队的操作对象具有相同的优先级并且在它们被放入队列时准备好执行——也就是说,它们的 isReady 方法返回 YES——它们将按照它们提交到队列的顺序执行。对于最大并发操作数设置为 1 的队列,这等同于串行队列。但是,您永远不应该依赖操作对象的串行执行。操作准备情况的更改可能会更改生成的执行顺序。

如果setMaxConcurrentOperationCount没有帮助,请尝试使用-isReady自定义中的方法NSInvocationOperation

于 2013-05-22T12:44:33.280 回答
0

使用并发队列时,您无法保证它们完成的顺序。但是,你真的不应该在意。让他们以最有效的方式完成。

不过,我原以为您希望文件名与kURL 的索引相对应。因此,我建议您将下载过程更改为仅k在发起请求时使用,并停止使用x,例如:

NSOperationQueue *queue = [NSOperationQueue new];
queue.maxConcurrentOperationCount = 5;   // limit number of concurrent requests to some reasonable number

NSString* appSuppPath = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* foofile = [appSuppPath stringByAppendingPathComponent:@"PSDB"];

for (int k = 0; k < [imageArray count]; k++)
{
    [queue addOperationWithBlock:^{
        NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:[imageArray objectAtIndex:k]]];
        if (imageData)
        {
            NSString * str = [NSString stringWithFormat:@"%@/%d.jpeg", foofile, k];
            [imageData writeToFile:str atomically:YES];
        }
    }];
}  

这消除了计数器的异步更新x,消除了文件编号问题。(这也解决了原始代码中的线程安全问题:如果两个下载同时完成,因此都使用相同的值x怎么办?)这也确保了您的文件被正确命名。

现在,如果您出于其他原因确实希望它们按顺序完成,您可以在串行队列中执行此操作(例如maxConcurrentOperationCount = 1),但这样做会导致显着的性能损失。设计你的架构要好得多,这样完成顺序就不重要了。例如,如果您只需要知道它们何时完成,则添加一个依赖于其他完成的完成操作。

当然,上面的代码更改解决了一个战术问题,但是如果您认为有其他原因需要它们按照排队的顺序完成,请告诉我们,因为可能存在不需要这样做的解决方案并让您享受并发下载带来的性能提升。

于 2013-05-22T13:20:13.553 回答