0

I am having few doubts about Combinations of GCD and queues, in iOS. let me put those here

First. According to IOS6 programming cookbook, here is small code snippet for downloading images using async and sync. and its as below

dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_async (concurrentQueue, ^ {
UIImage *image = nil;
dispatch_sync(concurrentQueue, ^ { /* download image here */ });
dispatch_sync(dispatch_get_main_queue, ^ { /* show the downloaded image here */ });
});

Second. I need to download few images from Url, meanwhile i need to update the progress view showing how many images have got downloaded. so i am using following code snippet

dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async (concurrentQueue, ^ { dispatch_sync(dispatch_get_main_queue, ^ { /* download image here and update progress view here */ });
});

kindly note that i am updating progress view on main thread. But my progress view is getting displayed after all images has been downloaded. i checked other links but was not pretty clear with the answers.not getting the reason for the problem. My code is as below.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{dispatch_sync(dispatch_get_main_queue(), ^{
       alert = [[UIAlertView alloc] initWithTitle:@"Please Wait Downloading reports..." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil] ;
       prgView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];
       prgView.frame = CGRectMake(10, 50, 270, 20);
       [alert addSubview:prgView];
       [alert show];
      prgView.progress=0.0;
       actual= 0.0;

       for(NSInteger i=0; i<[fileLinks count];i++)
       {

        //  [self downLoadFileFromUrl : fileLinks[i]: i ];
           NSLog(@"Url is %@", fileLinks[i]);
           NSLog(@"i value is %d", i);
           NSData *imagedata = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileLinks[i]]];
           NSString * _filename=  [fileLinks[i] lastPathComponent];
           NSMutableString *filePath = [[NSMutableString alloc] initWithFormat:@"%@", [VSCore getTempFolder]];
           [filePath appendString: _filename] ;
           [imagedata writeToFile: filePath atomically:YES];
           prgView.progress =((float) i /([fileLinks count]));
           NSLog(@" progress value is %f", prgView.progress);

       }
   });
});

so what is problem here? and my other doubt is, if any one wants to hold the user (displaying progress view or activity indicator) while performing long processing task, can't they do that in main thread ? (provided they are displaying progress bar or activity indicator), why we have to use combination of async, sync with concurrent thread or main thread etc etc.

and i am bit confused with, for what scenario i had to use the proper combination of async, sync, main queue , concurrent queue, serial queue. if any one give explains me or provide me good link for understand The combinations of async , sync and 3 queue. that will be great.

4

3 回答 3

2

您应该在主队列上创建和更新“UIProgressView”

并在另一个队列(不是主队列)上做你的工作

在做你的工作时,如果你想更新 GUI 上的任何对象,你应该在主队列上做

你可以这样做:

alert = [[UIAlertView alloc] initWithTitle:@"Please Wait Downloading reports..." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil] ;
    prgView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];
    prgView.frame = CGRectMake(10, 50, 270, 20);
    [alert addSubview:prgView];
    [alert show];
    prgView.progress=0.0;
    actual= 0.0;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for(NSInteger i=0; i<[fileLinks count];i++)
        {
            //  [self downLoadFileFromUrl : fileLinks[i]: i ];
            NSLog(@"Url is %@", fileLinks[i]);
            NSLog(@"i value is %d", i);
            NSData *imagedata = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileLinks[i]]];
            NSString * _filename=  [fileLinks[i] lastPathComponent];
            NSMutableString *filePath = [[NSMutableString alloc] initWithFormat:@"%@", [VSCore getTempFolder]];
            [filePath appendString: _filename] ;
            [imagedata writeToFile: filePath atomically:YES];

            dispatch_async(dispatch_get_main_queue(), ^{
                prgView.progress =((float) i /([fileLinks count]));
            });
            NSLog(@" progress value is %f", prgView.progress);
        }
    });

您可以阅读一本电子书:“Pro.Multithreading.and.Memory.Management.for.iOS.and.OS.X”(购买或询问 gg)

祝你好运!

于 2013-07-29T10:03:04.710 回答
0

async和sync的组合是对的,但是主线程和其他线程的组合会导致循环,尤其是在使用sync主线程的async线程中。

于 2013-07-29T09:12:27.560 回答
0

如果您仔细查看您的代码,您会注意到您实际上是在主线程中运行所有内容。

^{dispatch_sync(dispatch_get_main_queue(), ^{
       alert = [[UIAlertView alloc] initWithTitle:@"Please Wait Downloading reports..." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil] ;
       prgView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];
       prgView.frame = CGRectMake(10, 50, 270, 20);
       [alert addSubview:prgView];
       [alert show];
      prgView.progress=0.0;
       actual= 0.0;
       for(NSInteger i=0; i<[fileLinks count];i++)
       {

        //  [self downLoadFileFromUrl : fileLinks[i]: i ];
           NSLog(@"Url is %@", fileLinks[i]);
           NSLog(@"i value is %d", i);
           NSData *imagedata = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileLinks[i]]];
           NSString * _filename=  [fileLinks[i] lastPathComponent];
           NSMutableString *filePath = [[NSMutableString alloc] initWithFormat:@"%@", [VSCore getTempFolder]];
           [filePath appendString: _filename] ;
           [imagedata writeToFile: filePath atomically:YES];
           prgView.progress =((float) i /([fileLinks count]));
           NSLog(@" progress value is %f", prgView.progress);

       }
   });

这将在主线程中运行 downloadFileFromUrl 和进度视图的更新(除非 downloadFileFromUrl 是异步操作,我不知道)

基本上你需要在辅助线程中运行 downloadFileFromUrl 方法,然后只在主线程上运行这个位: prgView.progress =((float) i /([fileLinks count]));

于 2013-07-29T09:26:34.903 回答