Re: Best approach to long running tasks.
Re: Best approach to long running tasks.
- Subject: Re: Best approach to long running tasks.
- From: Ken Thomases <email@hidden>
- Date: Wed, 10 Sep 2008 09:13:12 -0500
On Sep 10, 2008, at 7:58 AM, Tom Fortmann wrote:
I'm looking for suggestions on how to best handle long running
tasks. My
app has a simple button connected to an Objective-C method. When I
click
the button the method is called and a series of steps are
performed. Each
involves some network activity and may take a second or two. I
would like
to update a status message on the screen as each step is performed.
I've
tried simply appending text to a text view, but none of the updates
get
displayed until the whole method completes. I also tried starting an
NSThread from the method, allowing it to return, and letting the
thread
update the text, but again nothing gets displayed until the thread
completes. Can anyone suggest a better way to handle this type of
application?
In general, you have to be very careful about performing GUI updates
from background threads. There are a lot of things that you shouldn't
do. See the Threading Programming Guide <http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/
>.
There are a couple of approaches to your problem. One is to use
asynchronous network APIs, like those provided by NSURLDownload,
NSURLConnection, NSFileHandle, and NSStream. The usual technique is
to create an object of a custom class to represent the overarching
task. This object maintains the state and coordinates the subtasks.
It uses one of the above classes to perform its subtasks in an
asynchronous fashion and uses the delegate or notification interface
that they provide to handle each event as subtasks complete.
The reason that your updates aren't being displayed on screen is
because you're not returning to the event loop, which displays any
windows which have views that have been marked as needing display.
You _can_ issue displayIfNeeded messages to force displaying outside
of the normal event loop, but it's discouraged. Often, if you find
yourself tempted to do that, it's a sign that your design is
problematic. You'll probably discover that your design will cause you
other problems, in addition to the display issues. For example, your
app won't be doing proper event handling, either. It will give the
user the spinning color wheel cursor, which is a bad sign. The user
won't be able to click any Cancel button, if you decide to implement
that. Etc.
There is another possible approach, which is to use a "modal
session". See the NSApplication methods beginModalSessionForWindow:,
runModalSession:, and endModalSession:.
Lastly, if you do use a background thread, it should not attempt to
perform GUI updates. Instead, it should inform the main thread of its
progress (using performSelectorOnMainThread:…). The method that you
invoke that way has the responsibility to update the GUI given the new
state supplied by the background thread.
Cheers,
Ken_______________________________________________
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