ios - Behavior differences between performBlock: and performBlockAndWait:? -


i'm creating nsmanagedobjectcontext in private queue handle data updates take files and/or services:

nsmanagedobjectcontext *privatecontext = [[nsmanagedobjectcontext alloc] initwithconcurrencytype:nsprivatequeueconcurrencytype]; appdelegate *appdelegate = [[uiapplication sharedapplication] delegate]; privatecontext.persistentstorecoordinator = appdelegate.persistentstorecoordinator; 

since i'm using private queue, don't understand difference between performblock: , performblockandwait: methods... perform data updates i'm doing this:

[privatecontext performblock: ^{          // parse files and/or call services , parse         // responses          // save context         [privatecontext save:nil];          dispatch_async(dispatch_get_main_queue(), ^{             // notify update user         });     }]; 

in case, data updates made synchronoulsy , sequentially, suppose correct place save context, right? if i'm doing wrong, i'd appreciate if let me know. on other hand, code equivalent?:

[privatecontext performblockandwait: ^{          // parse files and/or call services , parse         // responses          // save context         [privatecontext save:nil];     }];  // notify update user 

again guess correct place save context... differences between both methods (if any, in case)?

what if instead of performing synchronous service calls or files parsing, need perform asynchronous service calls? how these data updates managed?

thanks in advance

you correct in want moc must done within either performblock or performblockandwait. note retain/release thread safe managed objects, don't have inside 1 of blocks retain/release reference counts on managed objects.

they both utilize synchronous queue process messages, means 1 block execute @ time. well, that's true. see descriptions of performblockandwait. in event, access moc serialized such 1 thread accessing moc @ time.

tl;dr don't worry difference, , use performblock.

factual differences

there number of differences. i'm sure there more, here ones think important understand.

synchronous vs. asynchronous

performblock asynchronous, in returns immediately, , block executed @ time in future, on undisclosed thread. blocks given moc via performblock execute in order added.

performblockandwait synchronous, in calling thread wait until block has executed before returning. whether block runs in other thread, or runs in calling thread not important, , implementation detail can't trusted.

note, however, implemented "hey, other thread, go run block. i'm gonna sit here doing nothing until tell me it's done." or, implemented "hey, core data, give me lock prevents other blocks running can run block on own thread." or implemented in other way. again, implementation detail, change @ time.

i'll tell though, last time tested it, performblockandwait executed block on calling thread (meaning second option in above paragraph). information understand going on, , should not relied upon in way.

reentrancy

performblock always asynchronous, , not reentrant. well, may consider reentrant, in can call within block called performblock. however, if this, calls performblock return immediately, , block not execute until @ least executing block finishes work.

[moc performblock:^{     dosomething();     [moc performblock:^{       dosomethingelse();     }];     dosomemore(); }]; 

these functions executed in order:

dosomething() dosomemore() dosomethingelse() 

performblockandwait always synchronous. furthermore, reentrant. multiple calls not deadlock. thus, if end calling performblockandwait while inside block being run result of performblockandwait, it's ok. expected behavior, in second call (and subsequent calls) not cause deadlock. furthermore, second 1 execute before returns, expect.

[moc performblockandwait:^{     dosomething();     [moc performblockandwait:^{       dosomethingelse();     }];     dosomemore(); }]; 

these functions executed in order:

dosomething() dosomethingelse() dosomemore() 

fifo

fifo stands "first in first out" means blocks executed in order in put internal queue.

performblock honors fifo structure of internal queue. every block inserted queue, , run when removed, in fifo order.

by definition, performblockandwait breaks fifo ordering because jumps queue of blocks have been enqueued.

blocks submitted performblockandwait not have wait other blocks running in queue. there number of ways see this. 1 simple 1 this.

[moc performblock:^{     dosomething();     [moc performblock:^{       dosomethingelse();     }];     dosomemore();     [moc performblockandwait:^{       dosomethingafterdosomethingelse();     }];     dothelastthing(); }]; 

these functions executed in order:

dosomething() dosomemore() dosomethingafterdosomethingelse() dothelastthing() dosomethingelse() 

it's obvious in example, why used it. consider, however, if moc getting stuff called on multiple places. bit confusing.

the point remember though, performblockandwait preemptive , can jump fifo queue.

deadlock

you never deadlock calling performblock. if stupid inside block, deadlock, calling performblock never deadlock. can call anywhere, , add block queue, , execute time in future.

you can deadlocks calling performblockandwait, if call method external entity can call or indiscriminately within nested contexts. specifically, guaranteed deadlock applications if parent calls performblockandwait on child.

user events

core data considers "user event" between calls processpendingchanges. can read details of why method important, happens in "user event" has implications on notifications, undo management, delete propagation, change coalescing, etc.

performblock encapsulates "user event" means block of code automatically executed between distinct calls processpendingchanges.

performblockandwait not encapsulate "user event." if want block treated distinct user event, must yourself.

auto release pool

performblock wraps block in own autoreleasepool.

performblockadwait not provide unique autoreleasepool. if need one, must provide yourself.

personal opinions

personally, not believe there many reasons use performblockandwait. i'm sure has use case can't accomplished in other way, i've yet see it. if knows of use case, please share me.

the closest calling performblockandwait on parent context (don't ever on nsmainconcurrencytype moc because lock ui). example, if want ensure database has saved disk before current block returns , other blocks chance run.

thus, while ago, decided treat core data asynchronous api. result, have whole lot of core data code, , not have 1 single call performblockandwait, outside of tests.

life better way. have fewer problems did when thought "it must useful or wouldn't have provided it."

now, no longer have need performblockandwait. result, maybe has changed some, , missed because no longer interests me... doubt that.


Comments

Popular posts from this blog

java - UnknownEntityTypeException: Unable to locate persister (Hibernate 5.0) -

python - ValueError: empty vocabulary; perhaps the documents only contain stop words -

ubuntu - collect2: fatal error: ld terminated with signal 9 [Killed] -