我正在尝试使用enumerateObjectsWithOptions:usingBlock
方法枚举数组。但是,我的代码很少有用。如果它不起作用,我的应用程序会冻结(但没有沙滩球) - 我对块很新,所以我必须遗漏块操作才能顺利运行所需的东西。
注意:我知道我可以枚举使用for
循环,但这不是我想要的。
麻烦的代码:
NSArray*_storageCookies = [[NSArray alloc] initWithArray:[storage cookies]];
NSArray*_historyObjects = [[NSArray alloc] initWithArray:[_history webkitHistory]];
NSOperationQueue*_queue = [[NSOperationQueue alloc] init];
NSBlockOperation*_block = [NSBlockOperation blockOperationWithBlock:^{
NSAutoreleasePool*_pool = [[NSAutoreleasePool alloc] init];
[_storageCookies enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id ck, NSUInteger index, BOOL *stop)
{
NSString*domain = [ck domain];
[_historyObjects enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id object, NSUInteger aindex, BOOL *stop)
{
@synchronized(self)
{
NSAutoreleasePool*_pool2 = [[NSAutoreleasePool alloc] init];
NSString*_historyURL = [[NSURL URLWithString:[object url]] host];
if ([_historyURL rangeOfString:domain].location != NSNotFound)
{
NSHTTPCookie*cookie = [DAHTTPCookie createCookieWithURL:[ck domain] cookieName:[ck name] expires:[[ck expiresDate] timeIntervalSince1970] cookieValue:[ck value] browserType:DAWebkitBrowser secure:[ck isSecure]];
if ([_cookies containsObject:cookie] == NO)
{
[_cookies addObject:cookie];
}
}
[_pool2 release];
}
}];
}];
[_pool release];
}];
[_queue addOperations:[NSArray arrayWithObject:_block] waitUntilFinished:YES];
NSLog(@"Done - found %i Cookies...",[_cookies count]); //sometimes returns 0, sometimes the right number or nothing
修改
我修好了。你是对的,我的班级不是线程安全的。所以我必须添加一个@synchronized
块才能按预期工作。
答案 0 :(得分:4)
当你说“我正在使用for循环并且它有效”时,你的意思是你的for循环是同时运行还是它们有效地线性运行?
查看该代码,使用块没有任何问题。虽然如果不完全了解您正在使用的API,就无法确切地说,该代码中的基础算法实际上是爆炸性并行。
也就是说,每个循环都配置为尽可能多地尝试和处理内容。除非您调用的API的每一位都是线程安全的,否则您的代码可能会因为多线程冲突而崩溃和/或锁定(症状的随机性是并发问题的明确标志)。
即使所有API都是线程安全的,爆炸性并发也绝不是正确的并发模型。充其量,你会想要限制并发;你想使用某种机制来限制同时处理的垃圾量。
答案 1 :(得分:2)
我不知道_cookies的定义在哪里,但我想我们可以假设它是一个NSMutableArray。那些不是线程安全的,所以如果你有多个线程读取并同时向该数组添加对象,那就是一个问题。
有不同的方法可以解决这个问题。一种选择是创建拥有该数组的串行队列。在处理过程中,每次需要检查(如果需要添加)cookie时,在该队列上安排一个小块来完成这项工作。这样你就可以确保那些读取和添加都是严格连续的。
当然,还有其他一些想法。
然后退后一步,一旦你引入那种舞蹈以防止线程跨越那些_cookies,你可能会或可能不会发现这是最有效的实现。您需要使用实际数据对其进行测试。
另外,为什么NSOperation在这里?既然你无论如何等待结果,为什么不开始主队列上的枚举然后让它从那里扇出来呢? (我可能会遗漏一些东西)