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