This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Understanding NSRunLoop
Till now I know that every thread has its own runloop I don't know whether I'm thinking right.
I don't have a brief idea about nsrunloop but I'd like to know what is nsrunloop and what it's purpose and why all the thread has its own runloop(if I'm right). Please help me to let me know about nsrunloop.
a runloop is basically an extended while loop that works like C select call.
it is responsible for getting events from its sources and dispatching those.
mouse clicks, window moves, timers, stream events, ...... anything can be a runloop source.
thats the gist. read more about it in the countless dupes this has on SO or in the apple docs :)
Related
I am currently programming a Quiz-App for iphone using swift and xcode. Since a week I a stuck with a problem, i wasn't able so solve up to today.
Little Background Information:
All Questions are stored online on a server and are downloaded just in time. The Questions always contain images, so it takes some time to load them. This is why I am pre-loading the next question in background while the user is still thinking about the current question. Therefore I use the class QuestionLoader which extends Thread.
The Problem Situation:
When the user answers a question and presses the continue-button, the function goToNextQuestion() is triggered which shows the next question to the user. Either the pre-loading of the next question is finished and it can be shown instantly or the next question is still loading and we have to wait.
The Problem:
Now if we have to wait, I want to show a Loading-Label and -Indicator. Both are in the gui (placed with interface-builder) and hidden at the time. I do it like this:
func goToNextQuestion()
{
//check if next question is already ready
if (nextQuestionLoader.isFinished==false)
{
//not ready, so wait and show waiting indication
labelLoading.isHidden = false
loadingIndicator.startAnimating()
while(nextQuestionLoader.isFinished == false) {}
//question i now ready, hide waiting indication
labelLoading.isHidden = true
loadingIndicator.stopAnimating()
}
//so next question is ready and all good
}
What I want to happen is that when the user pressed continue and the next question is not ready yet, that the loadingIndicator and the labelLoading are shown until the question is ready.
Now what happens is that continue is pressed the there is nothing shown and the gui is blocked util the question is ready, then it shows the next question and the same thing happens with the following question.
Screenshots of the area of my gui that is concerned for better visualitzation
(Sorry for the different number of points gained in the screenshots, does not have to do with the problem, simply 2 different screenshots)
So the gui update does not happen before the question is loaded completely and does not happen immediately as it should!
Additional Information
I tried the showing of the loading indicators at other points of the code and they show correctly, so there is no problem with this.
When i put print-command before and after the while-loop and follow the output in the terminal, I see that the print-commands are correctly executed before and after the while-loop. But the gui-update does only happen afterwards
The function goToNextQuestion is completely executed in the main-thread!
So how can i achieve that the loading-indication is shown directly and after it is shown, the while-loop waits for the finish of the other thread?
I am really desperate because i have no idea at all how to solve this.
I would really really appreciate some help from you!
Thank you very much in advance for your time!!
There are several problems with your approach.
First, you should not use NSThread/Thread. The system class URLSession handles async downloading for you. (And creating threads is expensive and error-prone.) Use URLSession instead. You should be able to find lots of examples online, including here.
Second, you can't block the main thread like you're doing with your
while(nextQuestionLoader.isFinished == false) {}
Code. Since your download is running on a background thread it will keep running, but by blocking the main thread everything will freeze until the download completes. Your UI changes don't get a chance to be drawn on the screen until the download is complete.
What you should do is use URLSession using either a delegate method or a completion closure. It supports both approaches.
I have a project called Async_demo on Github that includes working code that shows how to use URLSession. It's a simplified example, but it should get you started.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
Is it ok to wait for an asynchronous request (say an NSURLSessionDataTask,) using a semaphore for example.
There is a lot of advice out there claiming that synchronous networking is bad, however I don't see that as grounds for refusing synchronous requests, especially when they're done in a background thread.
Synchronous requests (in a background thread/queue) have the benefit of not needing to be callback-nested.
The answer in https://stackoverflow.com/a/31563134/466604 shows only a method to achieve this, but it comes with implied discouragement. (Along with other discouragement from https://devforums.apple.com/thread/9606?tstart=0)
My question is whether discouraging this discouragement is warranted, given those synchronous requests happen in a background thread, primarily as a way to avoid nesting callbacks.
No, it's not ok. Don't do this.
iOS might even kill your app in the process. Besides, look at callbacks as they were the next step in your serial execution.
The processor needs those cycles to do other things, don't be a bully!
INSIGHT:
As #EricD said, if your execution fails for some reason, that thread is lost until you exit your app and the O.S. claims it back.
That thread is a valuable resource that must not be wasted and much
more valuable in Mobile Operating Systems as iOS.
iPhone's processors are not as powerful as nowadays Desktop' processors or GPU's processors that can build up to hundreds of thousands threads.
If you use a semaphore, you are waking up to ask that thread after some time, and if the conditions has not being met, then you go to sleep again. This is usually in the ms time, but still, is some time that the processor dedicate to something useless.
MORE CLEAR
When you define a callback, is as if you were to sleep and you say to somebody.
Don't call me, I will call you when I'm ready to go.
Instead, using a semaphore is like:
Is ok if you call me 1000..0 times to ask me if I'm ready to go
The overheading in this case is obvious...you usually needs a time to wake up and to sleep back again. That's wasted processor time
Keep in mind that in the best case you are using a semaphore that put the Thread into sleep for a while, and then ask again if it is OK to proceed.
If this is not the case, then this thread is using ALL the processor cycles assigned to it to ask you if it's ok to proceed, that is 100% CPU Usage in that Thread evaluating just a condition.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
Tell me if this make sense. This is an iOS question.
I'm seeing code where it is already in the main thread, but the code would dispatch_async all sorts of UI code to the main thread's queue. Layouts, animations etc etc.
I was told this some how speeds up responsiveness (example, when pushing a view controller, you would dispatch other UI ops there so it won't block the push transition.
This doesn't make sense because first it is dangerous, second, it doesn't guarantee when the UI code gets run(even though it will probably run with milliseconds). The only good reason I can see is for it to guarantee that the UI code is not accidentally run in a different thread.
What do you guys think?
There are definitely times you employ this pattern of dispatching back to the main queue, so I might not be too quick to dismiss it or label it as "dangerous" (though the way you characterize it, it does sound suspicious). You should share some code samples of how you're seeing this pattern being used, and we can comment further.
When would you dispatch to the main queue? The prototypical example is when you're doing something on a background queue, but then want to dispatch the UI updates back to the main queue, e.g.:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// do something time consuming here, like network request or the like
// when done, update the UI on the main queue:
dispatch_async(dispatch_get_main_queue(), ^{
// update the UI here
});
});
But I'm assuming this is not the sort of dispatch to the main queue you're talking about. I'm assuming from your comment where you have something on the main queue dispatching asynchronously right back to the main queue itself.
The reason you would do that is if you don't want the dispatched code to run immediately, but rather to be queued for the next iteration of the run loop. This lets the autorelease pool drain, lets the current method complete (and release any resources it might have been using), lets other dispatched tasks run first, gives the UI a chance to reflect any changes you may have initiated, etc.
A few examples of when some developers might do this include:
You might use this pattern if you want a method call itself recursively, but you want to yield back to the run loop, to let resources be freed, let the UI reflect any changes, etc. You're basically saying "ok, let this method finish, but in the next run loop, run this method again."
A little more suspect, I've seen this pattern in viewDidLoad where you want to give auto layout a chance to "catch up" and update the frames. E.g. there is a common third-party progress indicator that won't work if you just invoke it from viewDidLoad, but it works if you dispatch that update back to the main queue.
Having articulated reasons why I've seen developers dispatch back to the main queue from the main queue, itself, I must confess that many of these patterns suffer from code smell and are often better accomplished via different patterns. But these are a few examples that I've seen.
But, again, if you want assistance on your particular code sample, you have to share it with us. We can't tell what the developer intended without seeing the code sample.
This question already has answers here:
Understanding NSRunLoop
(6 answers)
Closed 9 years ago.
I have been reading some documents about run loop, but still can not understand it exactly.
As iOS is not open source, while NSRunLoop is special for iOS/Mac OS X platform, what is its real implementation inside?
If you have some kind of user interface, or other code that needs to listen to events (like network ports), you need a run loop. Every NSThread automatically gets its own run loop, and you very rarely have to concern yourself with them directly. The run loop is also in charge of creating and releasing autorelease pools.
For more information :
What is the basic difference between NSTimer, NSTask, NSThread and NSRunloop?
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
is it possible to call an action that contain heavy operations several times? like save button (I save the first object) and want to add others, but the app becomes so slow and I can't navigate to other views
You can always play around with heavy data saving related tasks in the background. You can distribute the content related stuff to various threads (queues), you need to separate the stuff which you are saving and if it is blocking your UI and making your app slow then you need to perform these heavy operations in the background.
Make sure, you do NOT perform any UI updation operation in the background. Try reading about GCD (how it works), how you can create a background Queue etc and how you can play around with it. I assume you might be using core data in order to save the contents on save button. Try reading about the Parent/Child Manage Context Objects. Play around with it a bit and move your heavy task to background, updation of UI will always be on Main or UI thread (which you can always do it by calling get_main_queue() if you are working with dispatch queues). Happy Coding. If you have specific code, which is doing this, then let us know. We will be glad to help. :)
You need to make sure that you aren't tying up the main UI thread of your application. A potential easy fix is to do your save operation on a different thread. Here is an example of how to do just that using Grand Central Dispatch: iPhone - Grand Central Dispatch main thread
Example:
//notice this saveQueue is a new dispatch queue that's been created.
dispatch_queue_t saveQueue = dispatch_queue_create("com.mycompany.myqueue", 0);
dispatch_async(saveQueue, ^{
//this command represents your long running operation
doSaveOperation();
dispatch_async(dispatch_get_main_queue(), ^{
//always update your UI on the main thread!
[self showCompleteMessage];
});
});