2011-12-25 24 views
1

我想通過使用enumerateObjectsWithOptions:usingBlock方法的數組來枚舉。但是,我的代碼很少有效。當它不起作用時,我的應用程序凍結(但沒有沙灘球) - 我對塊的相對較新,所以我必須錯過塊操作順利進行所需的一些東西。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

您仍在使用潛在的爆炸性併發算法。雖然現在起作用,但它很可能是非常無效的。 – bbum 2011-12-26 17:00:10

+0

好吧 - 我會如何加油?我是新來的這種枚舉,所以我很欣賞你可以給的任何建議! – Pripyat 2011-12-26 18:56:13

回答

2

我看不到_cookies在哪裏定義,但我想我們可以假設它是一個NSMutableArray。這些不是線程安全的,所以如果你有多個線程讀取,並且同時向該數組添加對象,那就是一個問題。

有不同的方法來解決這個問題。一種選擇是創建一個擁有該數組的串行隊列。在處理過程中,每次您需要檢查(如果需要添加)cookie時,請在該隊列上安排一個小塊來完成這項工作。這樣你可以確保這些讀取和添加是嚴格串行的。

當然還有其他的想法。

但是,後退一步,一旦您引入舞蹈以防止線程遍歷那些_cookies,您可能會發現這是最有效的實現。你需要用你的實際數據來測試。

另外,爲什麼NSOperation在這裏?既然你無論如何都在等待結果,爲什麼不直接在主隊列上啓動枚舉,然後讓它從那裏扇出呢? (我可能會丟失一些東西)

+0

NSOperation是爲了防止主線程變得過載。這個操作很大,因此將這樣的操作發送到主隊列可能會將所有內容鎖定。 – Pripyat 2011-12-25 17:04:24

+0

但是,如果您等待完成,則主線程將被阻止。 – 2011-12-25 17:09:21

+0

你是對的 - 我的班級不是線程安全的。在正確的位置添加「@ syncronized」調用修復了我的問題。 – Pripyat 2011-12-25 17:10:52

4

當你說「我正在使用for循環並且工作正常」時,你的意思是你的for循環是同時運行還是它們有效地線性運行?

查看該代碼,使用塊沒有任何問題。雖然在沒有完全瞭解您所使用的API的情況下無法確定地說,但該代碼中的底層算法實際上是,並行的是

也就是說,您的每個循環都被配置爲儘可能併發地嘗試和處理內容。除非您所調用的API的每一位都是線程安全的,否則由於多線程衝突,您的代碼可能會崩潰和/或鎖定(症狀的隨機性是併發問題的一個確定標誌)。

即使所有的API都是線程安全的,爆炸性併發幾乎不是正確的併發模型。充其量,你會想要限制併發性;你想使用某種機制來限制同時處理的垃圾數量。