We can have [NSOperationQueue new] addOperationWithBlock yet we do not have NSOperation withBlock?
I thought the way addOperationWithBlock is to create NSOperation first with that block and then add that to the queue. So we have a function that will do the whole thing but not the one that can do it one thing at a time?
Strange.
Are you looking for +[NSBlockOperation blockOperationWithBlock:]?
Related
I've used GCD before with dispatch_async for background-threading units of work like parsing data from a network request (in, say, JSON or XML), and it's WONDERFUL. But what if I have a background task that's going to run for the length of the application? Is dispatch_async still a good fit for this case, or is there a better way to implement it?
Sure, but create your own dispatch queue for it. (If you use a global queue, you may tie up that queue--or one of its threads--forever.)
dispatch_queue_t dispatchQueue = dispatch_queue_create("com.mycompany.myapp.ForeverOperation", DISPATCH_QUEUE_SERIAL);
dispatch_async(dispatchQueue, ^{
// worker routine
});
More traditionally, you would create an explicit thread for this, and if it will run forever, that might make more "sense". But the results are basically the same.
NSThread * myWorkerThread = [[NSThread alloc] initWithTarget:...
[myWorkerThread start];
If you need to communicate with other threads/queues, as always, standard synchronization techniques may be required.
This really has nothing to do with dispatch_async, which is merely one approach to doing something in a background thread. If you want to do something in a background thread, do it in a background thread! Just be aware that doing this constantly can be a drag on your app, since you've only got so much processing time and only so many processors; you may end up having to study that in Instruments. You might want to break up your task into little bits and do it in short chunks every so often. Both GCD and NSOperation can help with that.
Is it possible to call an asynchronus NSURLRequest from a thread(NSThread)?
If yes, then is this a good practice?
If no, then can any one can explain with code snippet that what can be the issue?
Thanks
It is possible, but usually not necessary. To do this, you would need to set up an NSRunLoop on your secondary thread.
Usually it's better to just use NSURLConnection from the main thread, it will still not block. For processing the downloaded data, you could easily use dispatch_async from the connectionDidFinishLoading: delegate method.
I have program that is crashing somewhere not really visible to programmer. It may have something to do with memory management but it definitively has something to do with multiple threads and more than 200 notification observers...
I would like to know if that kind of starting derived NSOperation object would ensure that all operations are being executed consequently as normal execution on one thread?
[operation start];
[operation waitUntilFinished];
I think what you're looking for is operationQueue.maxConcurrentOperationCount = 1 and then add all your operations to the NSOperationQueue. They will be executed serially, one after another.
No, it starts the operation and then blocks the calling thread until it is done.
I have a NSOperationQueue with a number of NSOperations in it. I want to ensure that a particular part of the code is not executed in parallel. I use a NSLock object like this:
[myLock lock]
some critical code
[myLock unlock]
Unfortunately instead of a blocking "lock" call I get the following error:
-[NSLock lock]: deadlock ( '(null)')
After some investigation I noticed that all NSOperations seem to run in the same thread. I drew that conclusion after logging the thread id with:
NSLog(#"Thread %#\n", self, [NSThread currentThread]);
All operations seem to run in the same thread. Even though they are running in parallel as operations.
Does that make sense? I am a little confused. Do I miss something? Do you see any problem with using NSOperation and NSLock together? (If not, then I am sure the error is in my code)
I solved it. I am using ASIHTTPRequest underneath. Apparently all HTTP calls are made in the same thread unless you override "+ (NSThread *)threadForRequest:(ASIHTTPRequest *)request".
Sorry.
I have a task that takes a rather long time and should run in the background. According to the documentation, this can be done using an NSOperationQueue. However, I do not want to keep a class-global copy of the NSOperationQueue since I really only use it for that one task. Hence, I just set it to autorelease and hope that it won't get released before the task is done. It works.
like this:
NSInvocationOperation *theTask = [NSInvocationOperation alloc];
theTask = [theTask initWithTarget:self
selector:#selector(doTask:)
object:nil];
NSOperationQueue *operationQueue = [[NSOperationQueue new] autorelease];
[operationQueue addOperation:theTask];
[theTask release];
I am kind of worried, though. Is this guaranteed to work? Or might operationQueue get deallocated at some point and take theTask with it?
There's nothing in the documentation to say what happens when the NSOperationQueue is released. It would be safest to assume there's no guarantee that theTask will get executed.
I would have guessed that an NSOperationQueue releases its tasks when it's released, but I've noticed that the tasks do complete and dealloc even if I release the queue immediately after adding the task. That said, I don't think I'd rely on that behavior - there's more to gain by storing the NSOperationQueue in an instance variable (and releasing it in dealloc). An instance variable will give you a way to call other methods on the queue (cancelAllOperations, setSuspended, etc).
Can't you use the [NSOperation mainQueue] object so that you don't need to worry about autoreleasing it? If you only need to add one task that seems to make the most sense to me.
http://developer.apple.com/mac/library/documentation/Cocoa/Reference/NSOperationQueue_class/Reference/Reference.html#//apple_ref/doc/uid/TP40004592-RH2-SW21
There's no guarantee that it's safe to release an NSOperationQueue while it's still working. I suspect it probably is safe and this guarantee will probably be added someday, but it isn't there now. However, the equivalent Grand Central Dispatch API does guarantee that you can safely release its queues when you're done using them and it will keep them around as long as it needs them. So if you're on a platform with GCD, you can use that to be sure it won't blow up in the meantime.
Alternatively, you could create a wrapper class that checks if a queue is finished and releases both the queue and itself when the queue is finished.