How can I signal one thread to wait until a download is finished and after that pass the data to waiting thread

匿名 (未验证) 提交于 2019-12-03 07:36:14

问题:

I have a singleton class to download some data from the web. I am calling the download method of the singleton class from other class 'A' inside a GCD Queue and the downloads starts. The same time I am also executing this download method from a class 'B' in a GCD Queue. In this situation I want to inform the Class 'B' to wait until the download is completed. And when the download is completed give a copy of the downloaded data to class 'B' also. Here I am trying to download the same file from two classes A and B, otherwise there is no problem in my implementation. How is it possible?

Means here I am calling the same method in different threads. So how can I signal the thread B that the same file download is in progress in thread A and when finished pass the data to thread B also

- (NSData *)Download:(NSString *)urlString{       // here I am doing all the downloading operations      return data; } 

回答1:

Downloader.h

// Signature of a block that is called with the downloaded data from a URL // when the download is complete typedef (void)(^)(NSData *) DownloadCompletedBlock;  // Public interface of a class that downloads data from URLs // Downloads take place on a private dispatch queue, which // downloads URLs one at a time // Previously downloaded URLs are cached in a dictionary // Every so often the cache should be processed to discard old // entries. This will stop the cache from growing too large. // Since all downloads happen on the same dispatch queue, // accesses to the cache are naturally serialized without the need // for a lock @interface Downloader : NSObject  // Download the contents of a URL // When the download is complete downloadCompleted will // be executed on the callbackQueue to pass the downloaded // data as a result // This is the method that thread A should call - (void)download:(NSString *)URLString      calbackQueue:(dispatch_queue_t)callbackQueue  completionBlock:(DownloadCompletedBlock)downloadCompleted;  // Download the contents of a URL blocking the thread that calls the // method - (NSData *)downloadBlocking:(NSString *)URLString;  @end 

Downloader.m

// Private implementation interface @interface Downloader ()  // The thread/queue on which all downloads take place @property (readwrite, atomic) dispatch_queue_t downloadQueue; // A cache of previously downloaded URLs @property (readwrite, atomic) NSMutableDictionary *cachedDownloads;  // Download the contents of a URL and cache them - (NSData *)downloadAndCacheUrl:(NSString *)URLString;  @end  // Implementation @implementation Downloader  // Create the download queue and cache - (id)init {   self = [super init];   if (self) {     downloadQueue = dispatch_queue_create("downloadQueue", NULL);     self.cachedDownloads = [NSMutableDictionary dictionary];   }   return self; }  // Download the URL aynchronously on the download queue. // When the download completes pass the result to the callback queue // by calling downloadCompleted on the callback queue - (void)download:(NSString *)URLString      calbackQueue:(dispatch_queue_t)callbackQueue  completionBlock:(DownloadCompletedBlock)downloadCompleted {   dispatch_async(self.downloadQueue, ^{     NSData *downloadedData = [self downloadAndCacheUrl:URLString];     dispatch_async(callbackQueue, ^{       downloadCompleted(downloadedData);     });   }); }  // Download the data blocking the calling thread // Use a block variable to store the result // Since the downloaded data is immutable, we do not need // to worry about synchronizing it or copying it // Use dispatch_sync to wait until the result is available // If the data is already in the cache because thread A downloaded it // then the cached data is used. // Since downloads happen serially, there is only ever one download happening // at a time so the download will only happen once - (NSData *)downloadBlocking:(NSString *)URLString {   __block NSData *downloadedData = nil;   dispatch_sync(self.downloadQueue, ^{     downloadedData = [self downloadAndCacheUrl:URLString];   });   return downloadedData; }  // Download the content of a URL. If the data has already been // downloaded and cached, then use the cached value - (NSData *)downloadAndCacheUrl:(NSString *)URLString {   NSURL *URL = [NSURL URLWithString:*)URLString];   NSData *downloadedData = [self.cachedDownloads objectForKey:URL];   if (downloadedData) {     return downloadedData;   }   downloadedData = [NSData dataWithContentsOfURL:URL];   if (downloadedData) {     [self.cachedDownloads setObject:downloadedData forKey:URL];   } }  @end 

Hope this is clear enough



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!