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: [email protected]
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 <[email protected]> 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 ([email protected])
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 [email protected]