0

Here is the problem.

  1. I have a method called -(void)searchingInBackground which is running in background (performSelectorInBackground).

  2. In this method, I have couple of different threads which are running in background too (performSelectorInBackground). Like this:

    -(void)searchingInBackground
    {
      @autoreleasepool {
        [self performSelectorInBackground:@selector(getDuplicatedPictures:) withObject:copyArray];
      }
    
      @autoreleasepool {
        [self performSelectorInBackground:@selector(getLocationsOfPhotos:) withObject:copyArray];
      }
    ... (and so on)
    }
    
  3. In each of functions in threads (ie. getDuplicatedPictures, getLocationsOfPhotos...) they will generate NSStrings at the end and I will use those strings to update my text field GUI.

  4. In order to update my text field GUI. I created a function called UpdateGUI which will use to help me update all of my NSStrings. Like this,

    -(void)UpdateUI
    {
       [_NumDupPhotosLabel(label for GUI)  setStringValue: resultDupPhotos(string from thread function which is getDuplicatedPictures in this case)];
        ....(includes all of my strings from threads)
    }
    
  5. Here is the problem, when I call this UpdateGUI using performSelectorOnMainThread in each of threads function. It will give me EXC_BAD_ACCESS. Here is what I did. For example:

    -(void)getDupicatedPictures
    {
         resultDupPhotos = .....;
         [self performSelectorOnMainThread:@selector(UpdateUI) withObject:nil waitUntilDone:YES];
    }
    
  6. If I do not use performSelectorOnMainThread, just set the values directly in those functions it works fine. I just want to better organize the code.

    -(void)getDuplicatedPictures
    {
         resultDupPhotos = .....;
         [_NumDupPhotosLabel  setStringValue: resultDupPhotos]; (works good and it will set the value to the GUI label)
    }
    

Could you guys tell me how to fix this? Thanks!!!

YU FENG
  • 888
  • 1
  • 12
  • 29
  • Do you need to use threads or could you use queues and GCD? – vikingosegundo May 22 '13 at 15:18
  • Maybe is a typo here, but you are using getDupicatedPictures instead getDup(l)icatedPictures and UpdateUI instead Update(G)UI – Vertig0 May 22 '13 at 15:18
  • If those spelling errors are corrected as Patricio mentioned and the error still happens, try enabling NSZombies to track it down. http://stackoverflow.com/questions/5386160/how-to-enable-nszombie-in-xcode – rmooney May 22 '13 at 15:23
  • BTW: Methods shouldn't be prefixed with `get` unless they are of a very specific type, which these aren't. Also, preoperties and ivars should be prefixed with lowercase letters. Method names should always start with a lowercase letter. – bbum May 22 '13 at 15:51
  • Thanks for your naming suggestions @bbum. :) – YU FENG May 22 '13 at 15:56

1 Answers1

1
  • ARC or no?

  • if you have a crash, post the backtrace

  • surrounding a performInBackground:... call with an @autoreleasepool does nothing (NSAutoreleasePool isn't going to help, either -- you need the autorelease pool to be in the thread of execution)

  • if a variable is involved in a crash, show the variable's declaration and initialization

  • spawning a bunch of threads simultaneously to do a bunch of work is likely to be slower than doing the work sequentially. Concurrency should always be controlled. If you have a long running task, you might likely want to spin up a second thread. Or you might want to re-order operations. The issue, though, is that running multiple threads at once, especially if those threads are doing a lot of I/O, is just going to increase contention and may likely make things slower, often a lot slower.

More likely than not, one of the objects calculated on a background thread is being released before the main thread tries to use it. How do you ensure that resultDupPhotos is valid between threads?

bbum
  • 162,346
  • 23
  • 271
  • 359
  • Thanks. I keep only one performInBackground thread and get rid of others. But I heard if one function runs like more than 5 second or so, we suppose to open a new thread, don't we? Also if the @autoreleasepool does nothing. What should I do? Should I create NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; in the function instead? – YU FENG May 22 '13 at 16:43