6 Replies
      Latest reply on Dec 27, 2018 1:30 PM by sjmills
      sjmills Level 1 Level 1 (0 points)

        We have code that calls

         

        return self.mainProgressBar.doubleValue;

         

        from a background thread. For the sets, it's easy to do this the correct way:

         

        dispatch_async(dispatch_get_main_queue(), ^{
             self.mainProgressBar.doubleValue = val;
        });

         

        But how does one fix this for returning a value from a property?

         

        After thinking about it, it was obvious. Too early in the day. Coffee hadn't kicked in. I did this:

         

        __block double               result = 0;
        
        // Note sync, not async, so it waits:
        dispatch_sync(dispatch_get_main_queue(), ^{
             result = self.mainProgressBar.doubleValue;
        });
        
        return result;
        • Re: Any way to fix "UI API called on a background thread" for gets?
          john daniel Level 3 Level 3 (340 points)

          Use a block just like the setter, but assign the result to a __block variable.

          • Re: Any way to fix "UI API called on a background thread" for gets?
            eskimo Apple Staff Apple Staff (10,775 points)

            If you do this (have a secondary thread call the main thread synchronously) you have to be very careful about deadlocks.  That’s because you typically want the main thread to be able to call your secondary thread synchronously — because the main thread often finds itself in need of immediate results — and you do both of these then you will eventually deadlock.

            Share and Enjoy

            Quinn “The Eskimo!”
            Apple Developer Relations, Developer Technical Support, Core OS/Hardware
            let myEmail = "eskimo" + "1" + "@apple.com"

              • Re: Any way to fix "UI API called on a background thread" for gets?
                sjmills Level 1 Level 1 (0 points)

                Hey Quinn - haven't spoken to you in ages. Good to see you're still doing your thing.

                 

                I'm pretty sure our main thread never calls our worker threads. But let's say it did: How would the worker thread GET NSProgressIndicator.doubleValue in an asyncronous way?

                 

                Or are you saying that both setting and getting the doubleValue should both be done synchronously?

                  • Re: Any way to fix "UI API called on a background thread" for gets?
                    eskimo Apple Staff Apple Staff (10,775 points)

                    Or are you saying that both setting and getting the doubleValue should both be done synchronously?

                    I’m saying that:

                    • In generally I recommend async for everything.

                    • If you do stuff synchronously, only do it synchronously in one direction.

                    With regards the last point, my experience is it’s better to reserve your synchronous direction for the ‘main thread to worker thread’ case because:

                    • The main thread is most likely to be the one that finds itself in a situation where it has to respond synchronously.  The worker thread is already doing with… well… threading, and thus it’s easier to adapt it to deal with the async call.

                    • The main thread can often experience significant latency, and thus a synchronous ‘worker thread to main thread’ call can end up blocking your worker thread for a while.

                    However, that’s only a rough guideline.  If you can guarantee that the main thread never calls the worker thread synchronously (either directly or indirectly) and that your main thread is always responsive, going the other way is feasible.


                    Taking a step back, I’m curious about the goal you described in your first post.  Why does your background thread need to get progress information from your UI?  Normally progress flows the other direction, that is, the UI updates based on progress being made by the background thread.

                    Share and Enjoy

                    Quinn “The Eskimo!”
                    Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                    let myEmail = "eskimo" + "1" + "@apple.com"