Re: Callbacks, GUI updates and threading
Re: Callbacks, GUI updates and threading
- Subject: Re: Callbacks, GUI updates and threading
- From: Hamish Allan <email@hidden>
- Date: Mon, 10 May 2004 00:55:29 +0100
Hi Brent, Andreas,
Thanks for your replies. I'd like to work the single-threaded model if
I can (I can increase the number of callbacks if necessary) but I'm
still not sure of the following:
Firstly: from where should I call the decoder? As I mentioned, the
window is not visible when loadDataRepresentation: ofType: is called,
and even windowDidLoad: is called before the window is visible. So I'd
really like to hook into proceedings a little later, i.e., just after
the window is visible, to create and run modally a sheet with a
progress bar and cancel button.
Secondly: if my decoder callbacks are to update the progressbar, I
presume they have to send [progressBar displayIfNeeded] after changing
its value, rather than just [progressBar setNeedsDisplay:YES] , because
the event loop will not be run again until that function returns (hence
the rainbow beach ball). But if that is the case, how will the events
from my 'cancel' button be handled? It seems to me that I'm definitely
going to need a separate worker thread, no? Also, do I need to call
performSelectorOnMainThread: displayIfNeeded, or will
setNeedsDisplay:YES or even just doubleValue (which should presumably
call setNeedsDisplay itself) do? Are (determinate) NSProgressIndicators
animated from the main thread?
Thanks again,
Hamish
p.s. Anyone used this:
http://iharder.sourceforge.net/macosx/threadworker/ ?
On May 9, 2004, at 16:44, Brent Gulanowski wrote:
These responses are just my own personal opinions:
On May 8, 2004, at 3:51 PM, Hamish Allan wrote:
Hi,
This is probably a bit of a newbie question (the cap fits and I'm
wearing it) but hopefully not a dumb one. I'm writing an audio
processing app and I've got a basic document framework in place. I'm
using libmad to decode MP3 data into PCM. Currently I'm doing this
all at load time, from within loadDataRepresentation: ofType:.
Therefore the program becomes unresponsive (spinning rainbow ball)
whilst the decoding happens.
Have a program in similar situation. Mine could take from 10 seconds
to a minute depending on resources of the computer.
I've implemented a callback in the document's controller which
currently just NSLogs a number between 0 and 1, and I've arranged for
it to get called about a hundred times. Which is fine for the
developer, but the user really wants to see a progress bar. So my
first question is this: can I cause GUI elements to be updated from
within my callback? It seems to me intuitively unlikely that any GUI
updates should occur before loadDataRepresentation returns, but I
could well be wrong about that.
A determinate vs indeterminate progress bar will require different
solutions -- you probably want a determinate one. My program combined
an indeterminate on e with a textual update of what was going on,
using a callback to send a string to the window controller which would
periodically update a textview with the "doing X" string. This is the
same as your logging a percentage, in structure. We could both use a
variation, which would involve a determinate progress bar and a
percentage complete estimate being sent to the window controller to
update the progress bar. This usually involves the bar growing at
annoyingly different speeds, but that's the standard situation (e.g.:
in Apple's Package Installer).
Then I think, that progress bar should have a 'cancel' button next to
it. And ideally, the window containing that progress bar and button
should actually be a sheet off the document's window. But the
document's window doesn't appear until loadDataRepresentation:
ofType: returns. I couldn't spot a documentDidFinishLoading method,
so how do I manage this?
If you want a cancel button, you could add a BOOL return value to the
callback for whether to continue processing. This can be determined by
running an event loop modally, which I have not tried. See the
NSApplication methods -runModalForWindow: and -runModalSession:.
I suppose my wider question is this: am I going to need to use
threads, or will callbacks be enough if the callback's return value
can cancel the operation and a responsiveness of (decoding time / n),
where n is currently 100, is enough?
You don't need a separate thread. It is probably overkill and then you
have to worry about locking and stuff, because you'll have to set a
flag from the main thread and read it from the working thread (or
maybe you can dispatch an event to the worker thread, but then you
have to check that the methods in AppKit you use are thread safe; I'm
speculating wildly here). Anyway you are still faced with the exact
same responsiveness problem: the work thread has to stop what it's
doing and check the status of the flag/event/callback, although I
suppose there is the option of just terminating the thread with
prejudice. I imagine that might have problems if you have a file open
and are in the middle of a read or something, but I really don't know
(it just feels like the number of variables increases unnecessarily).
Cheers,
--
Brent Gulanowski email@hidden
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.