Reputation: 13065
What is the best way to synchronize a data source which is updated frequently from a background thread with the GUI main thread?
Should i put a pthread mutex around each method call? This seems to be pretty heavy too me.
EDIT: I'm looking for a 10.5 solution
Upvotes: 1
Views: 1450
Reputation: 11330
Is this on Snow Leopard or do you wish to retain compatibility with 10.2+? If you're dead-set on keeping backwards compatibility, you can factor out the code that applies the updates to another method and call it using performSelectorOnMainThread:withObject:waitUntilDone:
Alternatively, if you'd prefer to play with new toys and keep your code more readable (i.e. keep the number of methods to a minimum), you could do it in-line courtesy of blocks and Grand Central Dispatch. Something like the following might suffice:
// The following line is (presumably) executed in your background thread
NSMutableArray *newEntries = [self doSomeHeavyLiftingInBackground];
dispatch_async(dispatch_get_main_queue(), ^{
/* The following lines are executed in the context of your main
thread's run loop. You don't need to mess about with locks as it
will not be executed concurrently with UI updates. */
id<NSTableViewDataSource> dataSource = [self getDataSource];
NSMutableArray *dataSourceInnards = [dataSource whyIsThisMethodHere];
[dataSourceInnards addObjectsFromArray:newEntries];
[dataSource tellTableViewToReload];
});
This has the advantage of not having to contort your code to the pass-a-single-object-to-a-separate-method pattern.
Upvotes: 1
Reputation: 3345
You could always update the model and table view on the main thread. There are functions in NSObject like performSelectorOnMainThread:withObject:waitUntilDone:
that allows you to easily perform a function call on the main thread. So you could update your model with:
[model performSelectorOnMainThread:@selector(addObject:) withObject:newObject waitUntilDone:YES];
and then, update your tableview with this:
[tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
Things get more complicated if you need to pass more than one object, because then you need to use invocations, but I've found that these functions can be used most of the time.
Upvotes: 2