I´m getting this error using NSLock which I tried to circumvent by using unlockWithCondition (using NSConditionLock), but regardless I get the same result:
* Break on _NSLockError() to debug.
* -[NSLock unlock]: lock ( '(null)') unlocked from thread which did not lock it.
I´m not sure if it´s bad, but what I´m doing is this:
new Thread:
[lockA lock];//waiting unlock
[lockB lock];//waiting unlock
..shared code..
[lockA unlock];
[lockB unlock];
in Main Thread:
//Do two HTTP request.
//when request respond, I unlock the locks in respective threads with [lockA unlock];
[lockB unlock];
So the section "..shared code.." can execute. I don´t understand why i´m getting this error.
Can anyone explain what I´m doing wrong? It´s look like it should work perfectly.
I think you're trying to use locks as semaphores here. Locks are meant to stop the background thread and the main thread from accessing something simultaneously. Hence, the thread holding the lock must release (unlock) it too.
If you want the background thread to wait for something to happen on the main thread, use semaphores.
Use GCD semaphores for nice and easy semaphores: https://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html
If you are doing your HTTP requests on NSURLConnection or similar and trying to unlock in the delegate, you need to be careful where you create and initiate the NSURLConnection from, as it should return to that thread, unless you explicitly use scheduleInRunLoop:mode to put it on another thread or run loop.
If you are certain that you're locking on the main thread, you should be unlocking on that thread. To get back there, you can use either performSelectorOnMainThread:withObject:waitUntilDone: callback or GCD to call back on the main thread using:
dispatch_async(dispatch_get_main_queue(), ^(void) {
...
});
With your unlocks in the ... space. You could use dispatch_sync() instead if you need to know the unlocks have completed before moving on.
However, using NSConditionLock, as you'd indicated you'd already tried is the solution. However, you still need to do the lock on the retrieval thread, not on the main thread. The condition will be guarded by your -unlockWithCondition: using a specific condition, so it won't unlock prior to the retrieval thread marking it as ready.
So, in your main thread, launch the retrieval threads. In each retrieval thread, -lock and then proceed to retrieve the data, then -unlockWithContidition:. In the consumer thread, use -lockWhenCondition and you should be fine.
The key is, though, that you have to lock and unlock on the same thread.
Related
What is synchronous and asynchronous in ios ? I am new in objective c. Which one i should use in my code while i am getting data from server. So please help me.
Thanks in advance.
You should always use asynchronous loading of network requests.
Asynchronous never block the main thread waiting for a network response.
Asynchronous can be either synchronous on a separate thread, or scheduled in the run loop of any thread.
Synchronous blocks main thread until they complete request.
For Demo code or turorial have a look into this link Asynchronous web service client using NSURLConnection and SBJSON
The majority of the time you will go for asynchronous calls for that kind of operations, otherwise you're UI will block because you are using the main thread.
Synchronous, as the name suggests the action will happen in synchronous with the run loop of your application.
To understand it better, say you have to display some data in UITableview after fetching the data from server.Imagine that the request and response from server takes like 3 seconds. When you are fetching this data synchronously from the server, your app will freeze for like 3 seconds between loading tableview and loading the data contents into that tableview
Now if you are sending your request asynchronously, your app won't freeze but it will load the tableview and tableview contents before the server can respond. In other words, your app won't wait for the 3 second of server response time.You have to take necessary delegate actions or blocks actions to check the response and reload the tabledata so that the server response is displayed in tableview.
Which method is better is pure choice what the developer wants and their app should behave but Apple documentation recommends if you are using synchronous calls do not initiate the call from current run loop.
Using asynchronous all threads are execute the operations parallel. So, Never block the main thread waiting for a network response.
Using synchronous all threads are execute the operations one by one. so, should wait until the other thread task done.
Hope It will be suitable.
Quick note based on other answers: dispatch_sync will not block the main thread unless you dispatch to the main thread.
Example:
// Block main thread because the main queue is on it.
dispatch_sync(dispatch_get_main_queue(), ^{ /*do stuff*/ });
// Block background thread.
dispatch_sync(my_work_queue, ^{ /*do stuff*/ });
A Synchronous call(blocking) is one that has to be completed before subsequent calls can be run in the same queue. It is given all of the processor time for that queue until it is complete. This makes it block the queue.
Asynchronous calls can be started in a queue, and then left running on another thread(processor time schedule), owned by that queue, while other calls are started with other threads.
It is very important to use dispatch_async for web calls because it may take time to get a result back and you want other tasks to be able to start in the queue and use it's threads. A common practice is to do web work, like downloading a file, on a custom background queue and then dispatch to the main queue when it is complete, to update the user.
There is more to this and you can read about dispatch queues from Apple, here.
I am a bit confused between the concept of asynchronous loading and main thread. When something is loaded asynchronously, does it mean that it is not run on the main thread? As far as I know this is two different concept, something can be run on the main thread asynchronously and something can also be run on the background/secondary thread asynchronously. Correct me if I am wrong.
Not quite. Running asynchronously means that it doesn't stop execution from continuing on the current thread. This is an important difference because it's totally possible to do something asynchronously such that it ends up on the main thread (for example: dispatch_async(dispatch_get_main_queue(), ^{ some block });), which would mean that it's not stopping some other thread from continuing, but is blocking the main thread.
Because the main thread is so important to applications, the most common use of asynchronous code is to avoid blocking it, but it's not the only use.
(edited to add)
It's more useful, perhaps, to think of it in terms of "async with respect to x". If you do this, for example:
dispatch_async(aSerialQueue, ^{
work();
work();
});
Then the two invocations of work are synchronous with respect to each other, and synchronous with respect to all other work on aSerialQueue, but asynchronous with respect to everything else.
Running something asynchronously simply means that the call may return before the task is complete. This may be because it's running on a background thread. It may be because it will happen later on the current thread.
Running something synchronously doesn't mean it will happen on the main thread; it means that the call won't return until the task is complete. That may be because it happens on the same thread. It may be because it happens on another thread, but you want the current thread to wait for the other thread to complete.
Further, note that there is a difference between the main thread and the current thread. A synchronous task called on a background thread will keep that background thread from moving on until the task is complete, but won't block the main thread at all.
Of course, most of the time in iOS, your code will be running on the main thread. But you can push work onto background threads (e.g. with the dispatch APIs), so the distinction is important.
The main thread is where the bulk of your code gets executed, including all of the UI. There are other threads as well, like a web thread and a networking thread, and you can create your own threads.
Synchronous vs Asynchronous is a matter of when your code will be executed. You can perform a sync or async block of code on the main thread, or any other thread. If it's in sync, it will block the rest of the thread until it finishes. If it is async, it will run whenever the thread frees up from whatever it is currently performing.
I have a call that goes to a server. I want the callback here to be run asynchronously in a secondary thread that's not the UI thread. Core Data here freezes up and I'd like to try to make the app feel more responsive. What's the best way to have this callback run in a secondary thread? Code example would be great!
[[SomeServer sharedInstance] doServerCallCallback:^(NSObject *param) {
NSManagedObjectContext *moc = [MYAPPDELEGATE managedObjectContext];
/* do more stuff with param */
[MYAPPDELEGATE saveManagedObjectContext];
}];
The server call itself doesn't need to be in a secondary thread, however the code executed in the block should be.
Putting some work on a background thread is easy: fire off your block with dispatch_async(), -[NSOperationQueue addOperationWithBlock:], or possibly even something related to the server connection you're using, like +[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]. (Look up any of those in the docs for usage examples.)
If you're looking to do Core Data stuff on your background thread, it gets nasty unless you're on iOS 5.0 or newer. Apple has a big writeup on Concurrency and Core Data for the pre-5.0 case, but the new stuff, while a whole lot easier for simple uses like you're proposing, isn't as well documented. This question should give you a good start, though.
The block that you're passing is an object that the server will execute at some point. If you want the block to be executed on a different thread, you'll need to change SomeServer's implementation of -doServerCallCallback:.
See the Grand Central Dispatch Reference manual for complete information about using blocks. In short, the server should create a dispatch queue when it starts up. You can then use a function like dispatch_async() to execute the block.
Is there any way I can kill a thread spawn through:
[NSThread detachNewThreadSelector:#selector(serverFetchInThread) toTarget:self withObject:nil];
The scenario I am working on is that in my main thread I am letting user enter data in my search bar and what ever user is typing I need to send to server for searching in a separate thread. Now, if user changes his selection by deleting old data and entering new data I do not want the previous thread to waste its time, kill it and spawn a new thread with new data.
Be there any other better way to handle this situation, please guide me.
No, there is no way to kill a thread from another thread. And for good reason as there is no way to do so in a fashion where the targeted thread is killed without risk of crashing the app.
To directly answer your question; you need to have some kind of a flag that indicates to the thread that it should stop doing whatever it is doing and exit.
However, a couple of questions are raised by your question:
First, why are you using threads and not using GCD? Concurrency via GCD or NSOperation is the generally recommended way to solve such problems.
Secondly, if you are talking to a server, are you using HTTP (most of the time, that is the case)? If so, why not directly use the asynchronous features of NSURL and friends?
Have a good look at using NSOperationQueue.
You can subclass NSOperation it to wrap up your server communications, and even make that queue serial (maximum operations = 1).
If a server operation is not yet finished and user has generated more input, you can cancel the existing one, and add the new one.
Due to the effect of the NSOperation wrapping your connection, you can just use the simple synchronous version and keep the connection handling very straightforward.
Also worth mentioning is compatibility. I would prefer to use GCD and blocks, but for compatibility, NSOperationQueue is required.
I'm using NSURLConnection in an iPhone application and the interface seems to slow down after sending initWithRequest: to my NSURLConnection instance. I'm not sure if this is occurring because my processing code is taking a long time to handle the response, or if it's because NSURLConnection is blocking the main thread.
Can anyone confirm that NSURLConnection will create the connection and wait for data on a separate thread, and then call its delegate methods on the main thread?
Thanks!
NSURLConnection supports two modes of operation: asynchronous and synchronous. Neither uses separate threads at all. They both use just one thread, that being whatever thread you run them in.
In synchronous mode, NSURLConnection will block whatever thread you run it in. Asynchronous mode uses the run loop to behave (from the developer's perspective) similarly to a background thread but with lower overhead and without any thread-safety issues. If using asynchronous mode, you want to run it in the main thread. It won't block anything.
If your interface is slowing down, that is not consistent with using NSURLConnection synchronously, which would instead cause your interface to stop completely until the request is complete.
If you follow apples example on NSURLConnection the call will be handled in a different thread than the main thread.