Re: NSPrivateQueueConcurrencyType working outside of performBlock
Re: NSPrivateQueueConcurrencyType working outside of performBlock
- Subject: Re: NSPrivateQueueConcurrencyType working outside of performBlock
- From: Trygve Inda <email@hidden>
- Date: Tue, 28 Jul 2015 15:32:47 -0700
- Thread-topic: NSPrivateQueueConcurrencyType working outside of performBlock
>
>> On Jul 28, 2015, at 10:14 AM, Trygve Inda <email@hidden> wrote:
>>
>>>>
>>>> On 28 Jul 2015, at 9:12 pm, Trygve Inda <email@hidden> wrote:
>>>>
>>>> I gather that when using NSPrivateQueueConcurrencyType, all operations (a
>>>> fetch for example) have to be done within a performBlock call.
>>>>
>>>
>>> ...
>>>
>>>> Then later, this context is used outside a performBlock:
>>>>
>>>>
>>>> NSArray *matchingQuakes = [taskContext
>>>> executeFetchRequest:matchingQuakeRequest error:&anyError];
>>>>
>>>>
>>>> Why does this work?
>>>
>>> You are supposed to call performBlock so that all accesses to the MOC are
>>> serialized on the queue and so you get thread safety that way. However it's
>>> quite possible to call the methods directly on the MOC in any thread context
>>> and they will work, all the performBlock() actually does is queue the same
>>> block of code onto the dispatch queue and when it's its turn, it executes by
>>> calling [ moc executeFetch.. blah blah].
>>>
>>> If you do that of course you have no thread safety any more and are likely
>>> to
>>> blow up. In this case there's only one thread (I believe) and so the
>>> accesses
>>> are serialized anyway and it works. It's a bad piece of code.
>>>
>>> I filed an enhancement report requesting that the coredata stack assert if
>>> you
>>> called a private queue MOC method from the wrong queue, I don't recall
>>> seeing
>>> anything come of it, however I do remember there is quite a lot of logging
>>> you
>>> can turn up on CoreData and it's possible one such log will tell you you're
>>> doing this.
>>
>> If I do use performBlock and have to do several things:
>>
>> This code is sitting inside a completion block for a URL downloader
>> {
>> [self doSomething];
>> [myContext performBlock (do more stuff)];
>> [self doSomethingElse];
>> }
>>
>>
>> Since the perform block will run in a different thread, how can I make sure
>> the "do more stuff" is finished before calling doSomethingElse?
>>
>> Or in this case would using NSConfinementConcurrencyType be better since it
>> is all within a completion block and presumably on it's own thread anyway.
>
>
> Use performBlockAndWait instead of performBlock.
>
> Or do something like (typed into Mail so not checked for syntax)
>
> [myContext performBlock:^{
> //do whatever operation with myContext
>
> // assuming you want doSomethingElse done on main queue
> dispatch_async(dispatch_get_main_queue(), ^{
> [self doSomethingElse];
> });
>
> }];
>
> I believe NSConfementConcurrencyType is deprecated so you should not use it
> for new code.
>
> I highly recommend you read through the documentation.
>
> https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Referen
> ce/CoreDataFramework/Classes/NSManagedObjectContext_Class/index.html
>
> HTH,
> Dave Reed
>
performBlockAndWait might work. In my completion handler I have basically:
Context = [self createPrivateContect];
For (I = 1; I < something ; i++)
{
...do stuff with completetion data from URL...
...do stuff with the context...
}
So I need to make sure the context stuff finishes before the for loop goes
onto the next pass through the loop.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden