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
Post a Comment