3

I'm trying to perform a 2 step process:

  1. Concurrent upload of photos
  2. User input then post content

, which is very similar to how facebook app works when you "Add Photo"

I want to start the upload of photos first in the background using the default NSOperationQueueDefaultMaxConcurrentOperationCount . These operations will return some info that I need to send together with the 2nd post.

However, due to the nature of the app and because of concurrency, how can I structure it in the way that I post the content only if the following conditions are met:

  1. All photos have been uploaded
  2. User action to post his content

A few scenarios can happen:

  1. No photos to post, user post content, the content should be posted immediately
  2. Photo uploads are complete, user post content, content should be posted immediately
  3. Photo upload is not complete, user post content, need to wait for all photos to upload finish before posting content.

I think I should create a photo upload NSOperationQueue and check for operationCount. If it's == 0, the content should be posted immediately when the user taps on the UIButton.

However, how do I wait if the photo upload is not complete? Should I be using waitUntilAllOperationsAreFinished in the following way in pseudocode:

// User taps on UIButton to post his content and this is in a ViewController
- void postMyContent:
{
   [self.photoUploadQ.waitUntilAllOperationsAreFinished]

   // Post my content now              
}

Is this correct? I can't add the 2nd Task to the photoUploadQ since it has the default concurrency.

I'm concern of deadlock / blocking because of the documentation:

When called, this method blocks the current thread and waits for the receiver’s current and queued operations to finish executing. While the current thread is blocked, the receiver continues to launch already queued operations and monitor those that are executing. During this time, the current thread cannot add operations to the queue, but other threads may. Once all of the pending operations are finished, this method returns.

If there are no operations in the queue, this method returns immediately.

Thanks!

Community
  • 1
  • 1
Nora Olsen
  • 983
  • 2
  • 10
  • 22
  • Read the documentation again. It looks like I can have the 2nd task to `addDependency` to all the photo upload `NSOperation`. I wasn't sure that you can have multiple dependent tasks. That also means that I can do a simple `operationCount` if there are none to be dependent of. – Nora Olsen Sep 11 '13 at 05:39
  • I shouldn't rely on the default? I guess this is dependent on the type of connection too. – Nora Olsen Sep 11 '13 at 06:00
  • ..pls share your updated code here for uploading images step by step use in xcode workspace – Priya May 25 '17 at 07:30

1 Answers1

1

A common operation queue pattern is to create an operation (in your case, the "post content" operation) which is dependent upon the completion of a series of other operations (in your case, the "image upload" operations) using the NSOperation method, addDependency. This way, although the queue may be concurrent, this "post content" operation will not commence until the other "image upload" operations are done.

You may also want to constrain your operation queue to something less than NSOperationQueueDefaultMaxConcurrentOperationCount because NSURLConnection generally only permits 5 or so concurrent operations anyway (and if you do more than that, some of them may eventually timeout).

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • I found this https://github.com/Weswit/utility-ThreadPool-ios too which helps when the queue does not respect the max count. – Nora Olsen Sep 11 '13 at 06:33
  • 1
    @NoraOlsen If that works for you, that's brilliant. I have to say that I do a lot of concurrent network operations and I've never experienced this behavior [they describe](http://blog.lightstreamer.com/2013/01/on-ios-url-connection-parallelism-and.html) whereby they claim that `maxConcurrentOperationCount` is not honored. If they used `NSInvocationOperation` or `NSBlockOperation`, it's not surprising they'd have problems, but with a properly implemented `NSOperation` subclass (employing the `isFinished` logic required for concurrent operations), I've never had problems. – Rob Sep 11 '13 at 06:59
  • 1
    I can confirm Rob's experience, too. I actually wrote a test where I was not able to reproduce the erroneous behavior of NSOperationQueue - provided NSOperation has been subclassed _correctly_. And, by the way, it's probably better to use a single connection at a time when transmitting large data, like images. – CouchDeveloper Sep 11 '13 at 07:28
  • Thanks. I don't have much experience in this area. For example: multiple M posts of N images each or M*N posts of 1 image each will be better? – Nora Olsen Sep 11 '13 at 07:37
  • 1
    I have tested too. Since I'm using RestKit/AFNetworking, I have not seen that behavior when NSOperationQueue does not respect `maxConcurrentOperationCount `. – Nora Olsen Sep 11 '13 at 09:21
  • @NoraOlsen....how to use above tool to for uploading multiple images concurrently...please explain more – Priya May 25 '17 at 09:39