3

I'm getting into NSBlockOperation and I have some questions. Notably, the documentation for addExecutionBlock says:

Discussion

The specified block should not make any assumptions about its execution environment.

Calling this method while the receiver is executing or has already finished causes an NSInvalidArgumentException exception to be thrown.

What kind of situation will throw NSInvalidArgumentException? What really doesn "while receiver is executing" mean? What can cause this?

Rob
  • 415,655
  • 72
  • 787
  • 1,044
Łukasz Szpyrka
  • 687
  • 1
  • 6
  • 24
  • 1
    you shouldnt make any assumptions about the environment means that you dont know any state if the execution hasnt started is going to start is running eight now or has finished. you also should not make assumptions that your task will need a certain time but use async method calls to check about the state of your execution. and if you start an execution altough their is currently one running or has finished this method will throw an invalidargumebtexception. thats what i understand. – hasan Jul 26 '14 at 00:02

2 Answers2

3

You can't use addExecutionBlock: to add an execution block while the operation is running or has already completed. That's all it means.

quellish
  • 21,123
  • 4
  • 76
  • 83
  • Does it mean also that I can't run another operation inside executing operation? – Łukasz Szpyrka Jul 26 '14 at 00:15
  • I don't think you can effectively run an operation within an operation. You could enqueue an operation from within an operation, but (assuming it's on the same queue), it would run after the current one. If you want to do things like this, you should look into dependent operations. Either way, operations inside operations doesn't have anything to do with `addExecutionBlock:` – quellish Jul 26 '14 at 01:40
  • "It would run after the current one" ... If it was a concurrent queue (which they are by default), it wouldn't necessarily wait for the current operation to finish. – Rob Jul 26 '14 at 19:09
  • 1
    Operations are concurrent or synchronous, not queues. NSOperationQueues always *schedule their operations* one after the other. A synchronous operation makes the queue wait until it's done before *executing* the next operation. These are important distinctions. – quellish Jul 26 '14 at 20:17
  • 1
    There are two completely unrelated uses of the use of the term "concurrent". Whether an operation is concurrent or not, it doesn't affect the `maxConcurrentOperationCount` of the queue itself. If an operation (concurrent or not) adds a new operation to a queue, that second one doesn't have to wait for the first one to finish before it starts. Don't get me wrong: I up-voted your answer about `addExecutionBlock`, as that's correct. But, when discussing distinct operations, if the first operation is slow enough, that second operation may start (and possibly even finish) before the first finishes. – Rob Jul 28 '14 at 01:45
  • `maxConcurrentOperationCount` is just that: the maximum number of *concurrent* operations that should be scheduled by the queue at once. Scheduled. Not executing. I never said a queue has to wait for the currently executing *concurrent* operation to finish before *executing* another *concurrent* operation. I said that *scheduling* is serial, not synchronous, and that a queue will be blocked while *executing* a *synchronous* operation. Queues schedule operations one at a time in FIFO order. – quellish Jul 28 '14 at 07:21
  • NSOperationQueue uses libdispatch as it's underlying concurrency mechanism. I would suggest reading the source. In my comments I made the distinction between *scheduling* and *executing*. These are two different things. You seem to be focused on executing exclusively. – quellish Jul 28 '14 at 17:42
  • I have. I have also disassembled NSOperation and NSOperationQueue in Foundation. You are submitting a task to be scheduled, not scheduling it. NSOperationQueue tracks the last *pending* operation, locks the queue, uses dispatch barriers, and enqueues based on the operation's priority, readiness, and other factors - and that is just NSOperationQueue. The underlying libdispatch does the actual scheduling. – quellish Jul 29 '14 at 00:28
  • I never said one concurrent operation had to "wait" for another concurrent operation to finish executing. I said they are *scheduled* in order. I have repeated this several times. – quellish Jul 29 '14 at 18:12
  • You said "you could enqueue an operation from within an operation but it would run after the current one." And "a synchronous operation makes the queue wait until it's done before executing the next operation." Both of these easily can be misread as to suggest that the latter operation wouldn't start executing until the first operation completely finished executing. I'm glad that's not what you were saying. Thanks for clarifying. – Rob Jul 30 '14 at 02:52
3

A block operation object can have zero or more execution blocks associated with it. When the block operation is started, all of its associated execution blocks are submitted for concurrent execution. The warning is that you can't add more execution blocks to the operation after this point.

You can create more block operation objects and add execution blocks to those. Each block operation is started separately from others, so the rule about adding more execution blocks is evaluated separately.

Typically, you would create a block operation, add whatever execution blocks to it that you want, and then queue the operation onto an operation queue. Once the operation has been queued, it might start at any time (subject to readiness, which is subject to dependencies). So, it's best to not attempt to add execution blocks once it's been queued.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154