Dear Roland,

Well, here is my pattern:

Dispatching the datasource modification / tableview reloadData code on the main 
thread. Waiting for it to be executed. And avoiding deadlocks by querying 
[NSThread isMainThread] and taking the appropriate action. This pattern works 
perfectly in my context, but requires more refinement if several threads have 
access to the controller.

Context: The controller is mostly called from a serial queue, sometimes called 
from the main thread.

Code [controller code]:

if ([NSThread isMainThread]) 
{
        MODIFY DATASOURCE
        RELOAD DATA
}
else
{
    self.continueFlag = NO;
    dispatch_async( dispatch_get_main_queue(), 
    [[^{
                MODIFY DATASOURCE
                RELOAD DATA
       self.continueFlag = YES;
     } copy] autorelease]);
     __WAIT_FOR(self.continueFlag, 1000);                       
}


REMARKS:
__WAIT_FOR is just a polling macro, wrapped around usleep(); periodically 
testing for a condition to become true before continuing (here: polling time = 
1000 µs).
The copy/autorelease may not be mandatory.

Jean

Institut de Chimie Moléculaire de l’Université de Bourgogne
(ICMUB) — UMR 6302

U.F.R. Sciences et Techniques, Bâtiment Mirande
Aile B, bureau 411
9, avenue Alain Savary — B.P. 47870
21078 DIJON CEDEX

T: +333-8039-9037 
F: +339-7223-9232
E: jean.sui...@u-bourgogne.fr

http://www.icmub.fr/185-JEAN-SUISSE_?id=331





On 27 avr. 2012, at 12:42, Roland King wrote:

> Not really no, not that I can think of, nothing simple at least. 
> 
> That's one issue with Cocoa's drawing code being main-thread only and with 
> things like NSTableView being totally tightly bound to their datasource and 
> delegate and liable to call them at any time (drawing, scrolling, just 
> feeling like it), and calling more than one method in a sequence (not 
> synchronized across the entire method call), using them cross-thread is 
> tricky indeed. 
> 
> I will be interested to see if there are some simple patterns people have 
> found to work, I haven't. In the one case I did this I batched my updates 
> into sets of adds, deletes and changes and then blocked (or at that time 
> performSelector'ed) them onto the main thread where they were applied to the 
> data model there. I can certainly see cases in which that's hard to do and 
> you want to adjust the data model on your thread and then just say redraw. 
> 
> On Apr 27, 2012, at 3:42 PM, Jean Suisse wrote:
> 
>> So if I understand you correctly alteration of the dataSource should always 
>> be performed on the main thread.
>> [implied: because requests for redraw or similar that do not come from my 
>> code will always run on the main thread. Is that right ?].
>> 
>> Done. Not easy, but done. (Things were a little more complicated than just 
>> dispatching a block).
>> 
>> Now, for the sake of knowledge, I would like to consider the case where I 
>> can't always alter the datasource on the main thread. What then ?
>> I recall assembly instructions (STI, CLI) to prevent IRQ from occurring 
>> inside a few line of code. 
>> Is there some way to prevent thread switching for a short time ? Do you know 
>> an other way to deal with the present issue (alteration of the dataSource of 
>> an NSTableView not performed on the main thread) ?
>> 
>> Jean
>> 
>> On 26 avr. 2012, at 21:47, Corbin Dunn wrote:
>> 
>>> 
>>> On Apr 26, 2012, at 3:23 AM, Jean Suisse <jean.li...@gmail.com> wrote:
>>> 
>>>> Dear Peter,
>>>> 
>>>> Thank you for your reply. Here is the requested code (see below). 
>>>> After more investigations, I would like to take back a previous statement, 
>>>> that the tableview was perfectly aware that the number of rows in the DS 
>>>> was changed. This is due to my inexperience in stepping through the code 
>>>> across multiple threads.
>>>> 
>>>> Here are the facts :
>>>> 
>>>> - Only the controller removes rows from the datasource. Either in response 
>>>> to user actions (canceling tasks) or as a result of a Task completed 
>>>> notification from a running task.
>>>> - Each change in the dataSource is immediately followed by a reloadData 
>>>> message sent to the TableView.
>>>> - Sometimes, randomly, the TableView requests a row index that is out of 
>>>> bounds by one index (e.g. row #5 when the dataSource contains only 5 
>>>> elements).
>>>> 
>>>> I am thinking that a redraw occurs in-between the removal of one element 
>>>> of the table and the reloadData message. 
>>>> For now, I did a quick fix for this issue by adding a category with 
>>>> "safeObjectAtIndex"…. But one way to be certain would be to ensure that 
>>>> the two messages (removal + reloadData) are sent without any 
>>>> thread/process switching occurring…
>>>> 
>>>> The code for numberOfRowsInTableView : (experimentList is an instance of 
>>>> NSMutableAray)
>>>> 
>>>> - (NSInteger)numberOfRowsInTableView:(NSTableView*)tableView
>>>> {  
>>>>    return self.experimentList ? [self.experimentList count] : 0;
>>>> }
>>> 
>>> This is fine as long as your experimentList is only ever modified on the 
>>> main thread.
>>> 
>>> It sounds like that isn't the case, which is why you have random problems.
>>> 
>>> corbin
>>>> 
>>>> On 26 avr. 2012, at 11:45, Peter Hudson wrote:
>>>> 
>>>>> 
>>>>> Can you post your code for     numberOfRowsInTableView:
>>>>> 
>>>>> Peter
>>>> 

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to