gpt4 book ai didi

iphone - dispatch_queue_t 仍然阻塞主线程

转载 作者:可可西里 更新时间:2023-11-01 03:29:48 32 4
gpt4 key购买 nike

我想触发一个方法并让它在后台运行——我不关心它启动后到底发生了什么。

所以在我的主 viewDidLoadMethod 中,我有我所有的常用代码和这个:

 dispatch_queue_t newImages = dispatch_queue_create("load image in background", NULL);
dispatch_async(newImages, ^{
[self getNewImages];
});
dispatch_release(newImages);

我的假设是创建队列,然后将函数调用设置为在后台线程中运行,我的应用程序将继续运行。事实并非如此。

是从该函数调用的所有内容都自动移动到后台线程,还是我现在需要确保没有其他可能的阻塞调用发生。

编辑 - 阻塞的代码:

-(void) getNewImages
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *lastImagesSyncDate = [defaults valueForKey:@"ImagesLastSyncDate"];

dispatch_queue_t newImages = dispatch_queue_create("com.mydomain.app.newimagesinbackground", NULL);
dispatch_async(newImages, ^{

for (Manufacturer *m in self.manufacturers)
{
NSString *myurl = [NSString stringWithFormat: kNewImagesURL, m.ManufacturerID ,lastImagesSyncDate];
NSString *manufacturerID = [m.ManufacturerID stringValue];
NSURL *url = [NSURL URLWithString:[myurl stringByReplacingOccurrencesOfString:@" " withString:@"%20"]];
__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setCompletionBlock:^{

// Use when fetching text data
NSString *responseString = [request responseString];
NSString *fileName =[documentsPath stringByAppendingPathComponent: [NSString stringWithFormat:@"newimages%@.plist", manufacturerID]];
[responseString writeToFile:fileName atomically:YES encoding:NSUTF8StringEncoding error:nil];
NSArray *array = [[NSArray alloc] initWithContentsOfFile:fileName];

for (NSDictionary* dict in array) {

NSString *fileName = [NSString stringWithFormat:@"%@/%@_tn.jpg?t=",manufacturerID, [[dict valueForKey:@"ItemID"] stringByReplacingOccurrencesOfString:@" " withString:@"%20"]];
NSString *savePath = [documentsPath stringByAppendingPathComponent:fileName];
NSURL *url = [NSURL URLWithString: [[NSString stringWithFormat:kProductImagesURL, fileName]stringByAppendingString:lastImagesSyncDate]];

__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setCompletionBlock:^{

int statusCode = [request responseStatusCode];
if (statusCode==200) {
NSData *responseData = [request responseData];
[responseData writeToFile:[savePath stringByReplacingOccurrencesOfString:@"%20" withString:@" "] atomically:YES];
}

}];
[request setFailedBlock:^{
// NSError *error = [request error];
}];
[request startAsynchronous];
}

[array release];
}];
[request setFailedBlock:^{
// NSError *error = [request error];
}];
[request startAsynchronous];
}

dispatch_async(dispatch_get_main_queue(), ^{
dispatch_release(newImages); //this executes on main thread
});
});
}

我假设这里只创建了 1 个队列,所有这些调用都添加到其中,一次运行 1 个,直到它们完成。我尝试了几种变体,它使我的应用程序陷入停顿 - 它没有崩溃,但主线程正在爬行。

更新:所以我终于明白,在我的队列中拥有所有这些异步 ASIHTTPRequest 正在创建大量线程,因此更新了我的代码,让队列将这段代码的长时间运行部分添加到队列中,并改用同步请求:

 for (NSDictionary* dict in array) {
dispatch_async(newImages, ^{
NSString *fileName = [NSString stringWithFormat:@"%@/%@_tn.jpg?t=",manufacturerID, [[dict valueForKey:@"ItemID"] stringByReplacingOccurrencesOfString:@" " withString:@"%20"]];
NSString *savePath = [documentsPath stringByAppendingPathComponent:fileName];
NSURL *url = [NSURL URLWithString: [[NSString stringWithFormat:kProductImagesURL, fileName]stringByAppendingString:lastImagesSyncDate]];

ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
NSError *error = [request error];
if (!error) {
int statusCode = [request responseStatusCode];
if (statusCode==200) {
NSData *responseData = [request responseData];
[responseData writeToFile:[savePath stringByReplacingOccurrencesOfString:@"%20" withString:@" "] atomically:YES];
}
}
});
}

现在我只需要弄清楚在哪里再次释放队列,我已经尝试了几种变体但没有成功。

最佳答案

首先,您应该将队列命名为 using reverse domain syntax ,例如“com.foo.myapp.backgroundwork”——这确保了唯一性和一致性。

其次,您正在立即尝试释放刚刚创建的队列(并且可能正在做一些工作)。不要那样做。而是在工作完成后释放队列。以下内容实际记录在 Concurrency programming guide 中,在“管理队列内存”下

dispatch_async(newImages, ^{
[self getNewImages];
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_release(newImages); //this executes on main thread
});
});

编辑: 在我自己重新阅读并发指南(我自己吃药)后,我了解到运行时实际上会清理一个在后台线程上达到 0 引用计数的 dispatch_queue,所以不应该阻塞您的用户界面。立即释放它仍然是一个坏主意,而是按照我演示的做法,您的任务在主线程上排队并进行清理。因此,事后看来,我认为您的 -getNewImages 方法可能会导致您的 UI 阻塞。您能否展示该方法的一些代码,以便我们排除这种可能性?

关于iphone - dispatch_queue_t 仍然阻塞主线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6497743/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com