By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,635 Members | 2,188 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,635 IT Pros & Developers. It's quick & easy.

Want form to show changing data. But it could be closed, or closing, during update.

P: n/a
I have public methods in a form. The main form calls them, to update
that form's display. This form is like a real-time view of data that
is changing.

But, the form may not exist (it is created / destroyed at user
request). I can check form != null to prevent incorrect access.

But, the form could disappear immediately after the check, before the
method is run. Or someone could click 'close' when it's in the middle
of an update. How do I prevent these problems? How do I make a form
easily displaying changing information stored elsewhere?

Zytan

May 22 '07 #1
Share this Question
Share on Google+
22 Replies


P: n/a
If all of this processing is happening on the UI thread, then your
routine will not be interrupted before it ends, because all of the
processing is occuring in a loop which is processing windows messages. Even
if someone clicks on the close button, that can't be handled until every
message before it is processed.

If the processing is happening on another thread, and you are updating a
form, then you will be calling Invoke before doing anything that happens on
the form. Because of this, all the calls that you are making to the main
form are going to be processed in that message loop. All you have to do in
your code is call IsDisposed before you process anything called by Invoke,
and if it is, exit the code (and subsequently, pass a value back indicating
that the form has been disposed).
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com
"Zytan" <zy**********@gmail.comwrote in message
news:11**********************@u36g2000prd.googlegr oups.com...
>I have public methods in a form. The main form calls them, to update
that form's display. This form is like a real-time view of data that
is changing.

But, the form may not exist (it is created / destroyed at user
request). I can check form != null to prevent incorrect access.

But, the form could disappear immediately after the check, before the
method is run. Or someone could click 'close' when it's in the middle
of an update. How do I prevent these problems? How do I make a form
easily displaying changing information stored elsewhere?

Zytan

May 22 '07 #2

P: n/a
If all of this processing is happening on the UI thread, then your
routine will not be interrupted before it ends, because all of the
processing is occuring in a loop which is processing windows messages. Even
if someone clicks on the close button, that can't be handled until every
message before it is processed.
Right, so the UI thread handles windows messages for *all forms? This
means all methods are synchronized, so that the close event handler
will never be executed when another method is in mid execution.
If the processing is happening on another thread, and you are updating a
form, then you will be calling Invoke before doing anything that happens on
the form. Because of this, all the calls that you are making to the main
form are going to be processed in that message loop.
The data gets updated in another thread. This thread will invoke
something to tell the form to update its display with the new data.
So, I will have to call MyDataForm.InvokeRequired, to see if the UI
thread is running the method. If it isn't, I'll make it run it, using
MyDataForm.BeginInvoke.

I use BeginInvoke to avoid deadlocks. (The main form calls Join()
which waits for threads to end, which means a thread cannot be waiting
for the main form with Invoke, or else deadlock). The data passed has
a lock around the call. This is perfect for Invoke. But, since
BeginInvoke returns immediately, and the caller will unlock, by the
time the UI thread processes the method in the future, it will be
accessing data without a lock. So, I have to make a copy of the
data! And call BeginInvoke with that copy. Whew.
All you have to do in
your code is call IsDisposed before you process anything called by Invoke,
and if it is, exit the code (and subsequently, pass a value back indicating
that the form has been disposed).
In the form's methods, I can call this.IsDisposed to see if the form
exists or not? The main form caller will have to check if the form is
null or not, as well, before the call.

To avoid the main form from caring if this form exists, I could call a
static method. It will call InvokeRequired (to see if it's in the UI
thread), then BeginInvoke (to force it to be in the UI thread), and
only at this time, I can check a local variable that says if the form
exists or not (which is set on load and close). I cannot check it
before, because BeginInvoke delays the actual method execution.

Ok, thanks for the ideas, Nicholas

Zytan

May 22 '07 #3

P: n/a
Right, so the UI thread handles windows messages for *all forms? This
means all methods are synchronized, so that the close event handler
will never be executed when another method is in mid execution.
Yes, because there is typically one message loop for a process. You can
have more than one, but that is atypical.
The data gets updated in another thread. This thread will invoke
something to tell the form to update its display with the new data.
So, I will have to call MyDataForm.InvokeRequired, to see if the UI
thread is running the method. If it isn't, I'll make it run it, using
MyDataForm.BeginInvoke.

I use BeginInvoke to avoid deadlocks. (The main form calls Join()
which waits for threads to end, which means a thread cannot be waiting
for the main form with Invoke, or else deadlock). The data passed has
a lock around the call. This is perfect for Invoke. But, since
BeginInvoke returns immediately, and the caller will unlock, by the
time the UI thread processes the method in the future, it will be
accessing data without a lock. So, I have to make a copy of the
data! And call BeginInvoke with that copy. Whew.
You shouldn't be calling Join. It's not the best way to synchronize
threads. You are going to shoot yourself in the foot eventually with it.
Also, calling this on the UI thread is a REALLY bad idea, since you are
going to hold up processing on the main form for an indeterminate period of
time.

From what I can tell is going on here is that you have a method that
calls Join in the main UI thread, which halts that thread from doing
anything. You then call BeginInvoke, which sends messages to the UI thread
to be processed. However, because you are held up in the method that called
Join, none of those messages get processed until the thread terminates, at
which point Join returns, and then the method exits, and all the
notifications that you have waiting get processed.

It's the same exact thing as if you were doing all the processing on the
main UI thread. You are gaining nothing by calling Join.

You really need to rethink what you are doing at this point.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com
May 22 '07 #4

P: n/a
On Tue, 22 May 2007 13:10:55 -0700, Zytan <zy**********@gmail.comwrote:
Right, so the UI thread handles windows messages for *all forms? This
means all methods are synchronized, so that the close event handler
will never be executed when another method is in mid execution.
Yes, sort of. The above statement needs qualification, as forms that are
created in a thread other than the main UI thread are handled in that
other thread. But as long as you never create a new form from other than
the main UI thread, all of the code in all of the forms that is executed
in response to windows messages will be executed on the main UI thread.

For what it's worth, I never have understood the point in using
InvokeRequired. I always just invoke. There's no harm in doing so on the
form's creating thread, and in most cases I know that I'm calling from
another thread anyway. The one possible "downside" is that you need two
methods instead of one (the thread-safe one, and the one that actually
does work), but frankly I don't like the pattern where a single method
does two completely different things depending on some flag anyway
(InvokeRequired in this case). And if the work you're doing is reasonably
short, it's easy enough to use an anonymous delegate instead (so all the
code winds up contained in a single method...obviously you can use an
anonymous method with any length code, but I think it's more suitable for
blocks of code that are a half-dozen lines or less).
The data gets updated in another thread. This thread will invoke
something to tell the form to update its display with the new data.
So, I will have to call MyDataForm.InvokeRequired, to see if the UI
thread is running the method. If it isn't, I'll make it run it, using
MyDataForm.BeginInvoke.
Uh...okay. Seems like more trouble, but if that's the way you want to do
it, it should work. :) See below for reasons you might want to
reconsider though...
I use BeginInvoke to avoid deadlocks. (The main form calls Join()
which waits for threads to end, which means a thread cannot be waiting
for the main form with Invoke, or else deadlock).
IMHO, it's generally a bad idea to use Join(). There are certainly some
cases where it's just the right thing, but I think for normal inter-thread
communications, it's not necessary and results in overly complicated
situations. For example:
The data passed has
a lock around the call. This is perfect for Invoke. But, since
BeginInvoke returns immediately, and the caller will unlock, by the
time the UI thread processes the method in the future, it will be
accessing data without a lock. So, I have to make a copy of the
data! And call BeginInvoke with that copy. Whew.
If you were using Invoke(), then you would be assured of synchronizing
access to the data via that mechanism. No locking required. Your code
would be much simpler, even accounting for whatever different mechanism
you require for the main form to be notified of the threads' completion.

Yes, given your use of Join(), using BeginInvoke() is the way around
having deadlocks. But you shouldn't have to use Join() in the first
place, and so the deadlocks you're fixing by using BeginInvoke() also
shouldn't be a problem.
In the form's methods, I can call this.IsDisposed to see if the form
exists or not? The main form caller will have to check if the form is
null or not, as well, before the call.
More complication. Note that the reason you are needing to check whether
the form is still around is because you're using BeginInvoke(). Your use
of BeginInvoke() also introduces a somewhat odd situation in that none of
the BeginInvoke() calls that you've made will actually execute until your
main thread leaves the Join() call. So not only does your form not get a
chance to do any updating for user feedback, you create a situation where
all of the possible feedback gets done all at once, regardless of the
intervals between when the processing has been completed, and all of that
feedback could conceiveably be executed *after* the form has been disposed.

If, instead, you used Invoke(), providing a different mechanism for the
main form to know the threads are done, the user would get timely feedback
as each thread finishes. In addition, if you provide a mechanism for the
threads to be interrupted (ie the main thread signals to them to exit
without finishing), then you could have a way for the user to just cancel
the processing altogether (which would be useful when the user closes the
form, or exits the application, or pushes a button that says "Stop
Processing", or whatever). You would want to be careful to not assume any
given thread actually got the signal; if you set it just as the thread was
exiting or updating the form, for example, it would be moot at that
point. But again, since you'd have a mechanism for each thread to notify
the main form about completion, this should not be a problem.
To avoid the main form from caring if this form exists, I could call a
static method. It will call InvokeRequired (to see if it's in the UI
thread), then BeginInvoke (to force it to be in the UI thread), and
only at this time, I can check a local variable that says if the form
exists or not (which is set on load and close). I cannot check it
before, because BeginInvoke delays the actual method execution.
Interesting. More complication. :) Note that all of this complication
basically stems from your use of Join(), which is requiring the use of
asynchronous invokes on the main form, which is causing all of these
synchronization issues. Stop using Join(), and all of the sudden
everything can be synchronous again, and the issues go away. :)
Ok, thanks for the ideas, Nicholas
For what it's worth, I think you read a lot into Nicholas' reply that
wasn't necessarily there. He answered your specific question, and gave
you good advice regarding how to deal with the potential for the form
disappearing before some thread tries to access it in some way. But I
didn't see anything in his reply that said it was a good idea to get into
that situation if you can avoid it. :)

Pete
May 22 '07 #5

P: n/a
You shouldn't be calling Join. It's not the best way to synchronize
threads. You are going to shoot yourself in the foot eventually with it.
Also, calling this on the UI thread is a REALLY bad idea, since you are
going to hold up processing on the main form for an indeterminate period of
time.
You're right.

Unfortunately, I can't change that, since it's in someone else's
code. And yes, my life would be easier if I didn't have to deal with
it.

How is the best way for the main thread to know when another thread
finishes? Should it set a value right before it terminates? That
means the main thread would need to poll for it. Maybe it should
trigger an event, but which event, and how? How would you do it?
From what I can tell is going on here is that you have a method that
calls Join in the main UI thread, which halts that thread from doing
anything.
On program shut down, Join is called to make sure the program doesn't
terminate before the threads are done their thing (they have shut down
code which should be run). That's the only purpose of Join in the
program.

Thanks, Nicholas

Zytan

May 26 '07 #6

P: n/a
For what it's worth, I never have understood the point in using
InvokeRequired. I always just invoke. There's no harm in doing so on the
form's creating thread, and in most cases I know that I'm calling from
another thread anyway.
Very true, and this is the case every time I call it, too. Thanks.
but frankly I don't like the pattern where a single method
does two completely different things depending on some flag anyway
(InvokeRequired in this case).
I would tend to agree with you, but it seems ok for this, since it
just calls itself, and it's kind of the same method, anyway. I would
be dead against it if it really were two different things.
IMHO, it's generally a bad idea to use Join().
Me, too. I only use it when the program ends. To ensure the main
thread does not terminate before the worker threads have finished up
properly.
If you were using Invoke(), then you would be assured of synchronizing
access to the data via that mechanism. No locking required. Your code
would be much simpler, even accounting for whatever different mechanism
you require for the main form to be notified of the threads' completion.
Right, and I agree.
Your use
of BeginInvoke() also introduces a somewhat odd situation in that none of
the BeginInvoke() calls that you've made will actually execute until your
main thread leaves the Join() call. So not only does your form not get a
chance to do any updating for user feedback, you create a situation where
all of the possible feedback gets done all at once, regardless of the
intervals between when the processing has been completed, and all of that
feedback could conceiveably be executed *after* the form has been disposed.
Ok, I see, and that's bad. Luckily Join() is called only once, when
the program is termianting. But, everything you said is true.
To avoid the main form from caring if this form exists, I could call a
static method. It will call InvokeRequired (to see if it's in the UI
thread), then BeginInvoke (to force it to be in the UI thread), and
only at this time, I can check a local variable that says if the form
exists or not (which is set on load and close). I cannot check it
before, because BeginInvoke delays the actual method execution.

Interesting. More complication. :) Note that all of this complication
basically stems from your use of Join(), which is requiring the use of
asynchronous invokes on the main form, which is causing all of these
synchronization issues. Stop using Join(), and all of the sudden
everything can be synchronous again, and the issues go away. :)
Ok, but, even without Join(), and using Invoke(), how can I make a
static method in the form invoke a method on the form itself (so it
can update the GUI in it)? Even if things are syncrhonized, how do I
get to that point of them being synchronized?

Another thread is updating the data, and a function in this thread
wants to tell the form to update its GUI to show the data. How can it
be synchronized to know if the form exists, and if so, invoke on that
form? The form may close between the check, and the call.
But I
didn't see anything in his reply that said it was a good idea to get into
that situation if you can avoid it. :)
Your points have helped a lot, Pete, so thank you. I agree using
Join() makes a mess, and dealing with needless synch issues is just
not worth it when a redesign can solve it.

Zytan

May 26 '07 #7

P: n/a
On Sat, 26 May 2007 12:32:49 -0700, Zytan <zy**********@gmail.comwrote:
> You shouldn't be calling Join. It's not the best way to synchronize
threads. You are going to shoot yourself in the foot eventually with
it.
Also, calling this on the UI thread is a REALLY bad idea, since you are
going to hold up processing on the main form for an indeterminate
period of time.

You're right.

Unfortunately, I can't change that, since it's in someone else's
code. And yes, my life would be easier if I didn't have to deal with
it.
It's not true that you can't change that. You can always create a new
thread of your own that itself is what waits for the worker threads. If
you own the main thread, you are never obligated to block the main thread
when you don't want to.
How is the best way for the main thread to know when another thread
finishes? Should it set a value right before it terminates? That
means the main thread would need to poll for it. Maybe it should
trigger an event, but which event, and how? How would you do it?
Well, it depends on what you want to do with the information and what the
main thread is doing. But let's assume your main thread isn't stuck at a
Join() and it's just doing it's normal message loop. Then the easiest
thing is to use Invoke() to run a method on the main thread that handles
whatever post-thread stuff you want to do. You can even do this via an
event on whatever class implements the thread, which the main thread can
then subscribe to (still having to do Invoke() in its handler, of course).
> From what I can tell is going on here is that you have a method that
calls Join in the main UI thread, which halts that thread from doing
anything.

On program shut down, Join is called to make sure the program doesn't
terminate before the threads are done their thing (they have shut down
code which should be run). That's the only purpose of Join in the
program.
While it may perhaps be a little less problematic to have the Join() only
happen during shutdown, IMHO it's still not a good idea. If you have no
better way to implement synchronization, then you should at least create a
secondary thread that itself calls Join() to wait, and then signals the
main thread to actually shutdown when everything else is done. This will
allow the main thread to continue to process UI events (though of course
you'll want to disable anything the user shouldn't be messing with once
the shutdown procedure has started, as well as make sure there's a message
somewhere for the user to explain that the shutdown is happening and that
they need to wait for things to finish).

Pete
May 26 '07 #8

P: n/a
On Sat, 26 May 2007 12:48:19 -0700, Zytan <zy**********@gmail.comwrote:
[...]
Ok, but, even without Join(), and using Invoke(), how can I make a
static method in the form invoke a method on the form itself (so it
can update the GUI in it)? Even if things are syncrhonized, how do I
get to that point of them being synchronized?
You call Invoke() from a static method the same way you'd call from an
instance method, except of course you need to explicitly specify the
instance on which you want to call Invoke(). Obviously this means you
need a reference to the form somewhere, but you're not going to get
anywhere without that, so I will take that for granted.

Note that if you were using an event to deal with this communication
issue, the delegate handler added to the event from the form would include
the reference to the form itself. I'm not really clear on why you're
using a static method, but even using a static method, going through an
event provides a clean way to include the reference to the form.
Another thread is updating the data, and a function in this thread
wants to tell the form to update its GUI to show the data. How can it
be synchronized to know if the form exists, and if so, invoke on that
form? The form may close between the check, and the call.
Well, IMHO that's a design problem. I don't think you should design your
code so that that could happen. In particular, it sounds as though you
have threads that can continue to run after your form is closed. But
really, that's a bad idea if you expect those threads to want to
communicate with your form.

Instead, it would be much better to simply have the form not close until
the threads are done. That way, you can be sure that when you go to
Invoke a delegate on the form, the form will still be there.

Pete
May 26 '07 #9

P: n/a
Well, it depends on what you want to do with the information and what the
main thread is doing. But let's assume your main thread isn't stuck at a
Join() and it's just doing it's normal message loop. Then the easiest
thing is to use Invoke() to run a method on the main thread that handles
whatever post-thread stuff you want to do. You can even do this via an
event on whatever class implements the thread, which the main thread can
then subscribe to (still having to do Invoke() in its handler, of course).
Ok, so I have this: the main thread responds to a stop/quit command,
signals the worker thread to termiante. Now, instead of calling
Join(), the method just exits, and the main thread continues
processing messages. When the worker thread terminates, it Invoke()'s
an event, and THIS method continues the program termination.

I think that would be fine.
While it may perhaps be a little less problematic to have the Join() only
happen during shutdown, IMHO it's still not a good idea.
Agreed.
If you have no
better way to implement synchronization, then you should at least create a
secondary thread that itself calls Join() to wait, and then signals the
main thread to actually shutdown when everything else is done.
Join() is just used because it's so easy, more than anything else. If
there was a better way that wasn't complicated, which I think you've
explained above, then I'll try and get that used that instead.
This will
allow the main thread to continue to process UI events (though of course
you'll want to disable anything the user shouldn't be messing with once
the shutdown procedure has started, as well as make sure there's a message
somewhere for the user to explain that the shutdown is happening and that
they need to wait for things to finish).
Yup, I already basically do that, since right now, the entire form is
frozen (from the GUI thread being paused from Join()), so I had to at
least say something is going on during this time!

Thanks, Pete! :)

Zytan

May 28 '07 #10

P: n/a
You call Invoke() from a static method the same way you'd call from an
instance method, except of course you need to explicitly specify the
instance on which you want to call Invoke(). Obviously this means you
need a reference to the form somewhere......[snip]
Yup, and that's the issue, to have that reference, and to use it when
it could change on you at any moment.
Well, IMHO that's a design problem. I don't think you should design your
code so that that could happen. In particular, it sounds as though you
have threads that can continue to run after your form is closed. But
really, that's a bad idea if you expect those threads to want to
communicate with your form.

Instead, it would be much better to simply have the form not close until
the threads are done. That way, you can be sure that when you go to
Invoke a delegate on the form, the form will still be there.
Pete, the data is coming through a socket connection, and who knows
when the data will arrive. Since the form is just to show the current
stream of data, and is not the main form, I don't want the form to
exist for all time, and be processing all the time (it takes up memory
and CPU resources). I want it to allow it to be opened/closed as
desired. When open, it will show the current data (but also update in
real-time).

Right now, this socket thread checks to see if the form exists, and if
so, invokes a method on it to update itself. There's still that
little chance the form could disappear right AFTER the existance
check, but BEFORE the reference is used to invoke. Things are
properly synch'ed AFTER the invoke, but not before, so that's the
danger area. (I could catch exceptions to prevent a crash, I
suppose).

Zytan

May 28 '07 #11

P: n/a
On Mon, 28 May 2007 09:54:23 -0700, Zytan <zy**********@gmail.comwrote:
Ok, so I have this: the main thread responds to a stop/quit command,
signals the worker thread to termiante. Now, instead of calling
Join(), the method just exits, and the main thread continues
processing messages. When the worker thread terminates, it Invoke()'s
an event, and THIS method continues the program termination.
Yes, with some clarifications:

If you have multiple worker threads, you will of course need to implement
logic so that the "close application" code doesn't run until all of the
threads have completed.

Also, you have to do some overriding of the default Form class behavior,
since normally closing the main form will close the application.
Specifically, make sure that in the OnClosing() event handler, you cancel
the close unless all of the worker threads are done.

But yes, the basic idea is correct. Instead of actually closing the form
when the user asks you to, defer that until you've gotten through all the
necessary worker thread cleanup you need to do.
[...]
Yup, I already basically do that, since right now, the entire form is
frozen (from the GUI thread being paused from Join()), so I had to at
least say something is going on during this time!
This problem will go away if you do the above, but I want to mention: it's
not just that the GUI is unresponsive. If something causes your form to
be in need to redrawing, that won't happen if you're not processing
messages. Examples include another application coming to the foreground
and covering up your form, your form getting dragged partially off-screen,
that sort of thing. Anything like that would result in a blank form, not
even the message to the user telling them they need to wait.

I hope that it's obvious why that's not a very user-friendly behavior. :)

Pete
May 28 '07 #12

P: n/a
On Mon, 28 May 2007 10:02:05 -0700, Zytan <zy**********@gmail.comwrote:
>You call Invoke() from a static method the same way you'd call from an
instance method, except of course you need to explicitly specify the
instance on which you want to call Invoke(). Obviously this means you
need a reference to the form somewhere......[snip]

Yup, and that's the issue, to have that reference, and to use it when
it could change on you at any moment.
Well, as I mentioned, subscribing to an event is a very common way to
implicitly allow some component publishing that event to reference the
subscriber (your form in this case). The form instance itself will not
disappear as long as it's still subscribed to the event, though you may of
course still need some logic to check on whether the form's been
disposed. That said, there are probably better ways around the issue.
Pete, the data is coming through a socket connection, and who knows
when the data will arrive.
Is it correct to assume that the stream of data exists whether or not the
form is open?
Since the form is just to show the current
stream of data, and is not the main form, I don't want the form to
exist for all time, and be processing all the time (it takes up memory
and CPU resources). I want it to allow it to be opened/closed as
desired. When open, it will show the current data (but also update in
real-time).
A couple of points:

1) I think it's not really all that significant a consumption of memory
and CPU resources to keep the form around all the time. In fact, IMHO
this may be your very best solution as its nice and simple and avoids a
lot of the synchronization hassles you're dealing with. This definitely
falls into the category of "don't waste time optimizing something until
you know it's a bottleneck". I doubt that you'd find your form is a
bottleneck, especially since it seems that it's okay to have it around at
least some of the time.

2) If you insist that you need to be able to open and close the form at
will, it may be better to create a producer/consumer type interface, in
which a third data structure that is always present maintains the list of
data to be displayed. Your i/o code would produce data onto the list, and
the form would consume data from the list. The list could include some
semantics that the form could apply that cause it to discard data and stop
actually enqueuing new data when the form closes. That way, the data
structure is always around, but when the form isn't using it, it basically
does nothing (just ignoring any input from the i/o code).
Right now, this socket thread checks to see if the form exists, and if
so, invokes a method on it to update itself. There's still that
little chance the form could disappear right AFTER the existance
check, but BEFORE the reference is used to invoke. Things are
properly synch'ed AFTER the invoke, but not before, so that's the
danger area. (I could catch exceptions to prevent a crash, I
suppose).
I think there are better ways around the issue, but at the very least, you
could use some sort of synchronization object that is acquired by threads
wanting to Invoke() as well as the form's thread when it wants to close
itself. The threads would use some sort of "try" semantics on the
synchronization object (the exact syntax would depend on the object) so
that they can detect the closing case.

But, again...if you fix things so that the form is guaranteed to not close
itself until the threads are done invoking methods on it, then the
synchronization issue goes away (or rather, it's solved elsewhere, in an
easier-to-deal-with way).

Pete
May 28 '07 #13

P: n/a
Yes, with some clarifications:
>
If you have multiple worker threads, you will of course need to implement
logic so that the "close application" code doesn't run until all of the
threads have completed.
Yes. I have just one worker thread.
Also, you have to do some overriding of the default Form class behavior,
since normally closing the main form will close the application.
Specifically, make sure that in the OnClosing() event handler, you cancel
the close unless all of the worker threads are done.
Ok, beacuse that could be invoked by someone clicking the 'x' close
button. So, I have to defer the reaction until later. I'd have to
make it check some boolean that is set only when every thread is done
computing.
This problem will go away if you do the above, but I want to mention: it's
not just that the GUI is unresponsive. If something causes your form to
be in need to redrawing, that won't happen if you're not processing
messages. Examples include another application coming to the foreground
and covering up your form, your form getting dragged partially off-screen,
that sort of thing. Anything like that would result in a blank form, not
even the message to the user telling them they need to wait.

I hope that it's obvious why that's not a very user-friendly behavior. :)
Yes, I know all about these painting issues. Surprisingly, some large
commerical applications have these same flaws, in mid-operation, and I
think people just don't notice because they are not often covered up
by other applications (and when they are, people just think their
computer is slow).

Thanks for all the tips!

Zytan

May 28 '07 #14

P: n/a
Well, as I mentioned, subscribing to an event is a very common way to
implicitly allow some component publishing that event to reference the
subscriber (your form in this case). The form instance itself will not
disappear as long as it's still subscribed to the event, though you may of
course still need some logic to check on whether the form's been
disposed. That said, there are probably better ways around the issue.
Ok, let's deal with these other ways, then. Subscribing the form to
an event sounds complicated, and potentially error prone (for me).
Pete, the data is coming through a socket connection, and who knows
when the data will arrive.

Is it correct to assume that the stream of data exists whether or not the
form is open?
The stream of data is always there, but could be shut off if the
connection fails. I don't think the form cares about this, though, it
will just be nudged to update its display whenever the stream gets
some data (if ever).
A couple of points:

1) I think it's not really all that significant a consumption of memory
and CPU resources to keep the form around all the time. In fact, IMHO
this may be your very best solution as its nice and simple and avoids a
lot of the synchronization hassles you're dealing with. This definitely
falls into the category of "don't waste time optimizing something until
you know it's a bottleneck". I doubt that you'd find your form is a
bottleneck, especially since it seems that it's okay to have it around at
least some of the time.
My first attempt at a solution was to leave the form there for all
time. But, before I call MyForm.Show(), all of the events to update
the form were cached away (somehow?) awaiting to be used, and when the
form was shown 2 hours later, the CPU was overwhelmed with input (I
think, it was a mess, so many errors I didn't know what was
happening). The form must not really exist to accept input until
Show() is called, I concluded.

Also, I use RichTextBox to show some data, and it is just extremely
slow, even on a fast machine, I have see this be a bottleneck in CPU.
2) If you insist that you need to be able to open and close the form at
will, it may be better to create a producer/consumer type interface, in
which a third data structure that is always present maintains the list of
data to be displayed. Your i/o code would produce data onto the list, and
the form would consume data from the list. The list could include some
semantics that the form could apply that cause it to discard data and stop
actually enqueuing new data when the form closes. That way, the data
structure is always around, but when the form isn't using it, it basically
does nothing (just ignoring any input from the i/o code).
That's pretty much what I do now. It's not critical that I have an up-
to-date snapshot, I just want to show the current data streaming in,
so I just let the form be empty on load, and display the incoming data
(if it arrives).

My only issue is when the socket thread calls my (static)
MyForm.UpdateWithNewData(), this method checks to see if a form
exists, and if so, invokes a call in it (at which point we are
synch'ed). Since the form could disappear before the Invoke, I catch
exceptions, and deal with them.
I think there are better ways around the issue, but at the very least, you
could use some sort of synchronization object that is acquired by threads
wanting to Invoke() as well as the form's thread when it wants to close
itself. The threads would use some sort of "try" semantics on the
synchronization object (the exact syntax would depend on the object) so
that they can detect the closing case.

But, again...if you fix things so that the form is guaranteed to not close
itself until the threads are done invoking methods on it, then the
synchronization issue goes away (or rather, it's solved elsewhere, in an
easier-to-deal-with way).
It is so complicated to use synch objects, when all I want to do is
have a thread say "hey, you there? here's some data if you are".
Because I decided to not have the form around for all time, I just
make it open/close in response to the user. When it opens, the data
shown is blank. When a socket gives it data, it will call a (static)
method that says "hey, if you're there, update with this data" via
invoke. And I catch exceptions around the Invoke / InvokeRequired
calls to ensure that the form didn't disappear right at that moment.

It works right now. I haven't stress tested it. With the exception
catchers, it should be ok for those 1 in 1,000,000 chances of the form
closing right when i thought it still existed.

Thanks for all your help, Pete!

Zytan

May 28 '07 #15

P: n/a
On Mon, 28 May 2007 14:25:57 -0700, Zytan <zy**********@gmail.comwrote:
>[...] Your i/o code would produce data onto the list, and
the form would consume data from the list. The list could include some
semantics that the form could apply that cause it to discard data and
stop
actually enqueuing new data when the form closes. That way, the data
structure is always around, but when the form isn't using it, it
basically
does nothing (just ignoring any input from the i/o code).

That's pretty much what I do now.
It doesn't sound that way to me.
It's not critical that I have an up-
to-date snapshot, I just want to show the current data streaming in,
so I just let the form be empty on load, and display the incoming data
(if it arrives).

My only issue is when the socket thread calls my (static)
MyForm.UpdateWithNewData(), this method checks to see if a form
exists, and if so, invokes a call in it (at which point we are
synch'ed). Since the form could disappear before the Invoke, I catch
exceptions, and deal with them.
The key to what I suggested, and the big difference between that and what
you're actually doing, is that you are still trying to push data. The
form should be pulling data. If you leave it to the form to consume data
from your queue, then obviously you will never be in a situation in which
some code tries to update the form when it's not there.

Pete
May 28 '07 #16

P: n/a
The key to what I suggested, and the big difference between that and what
you're actually doing, is that you are still trying to push data. The
form should be pulling data. If you leave it to the form to consume data
from your queue, then obviously you will never be in a situation in which
some code tries to update the form when it's not there.
Oh, I didn't follow this is what you were saying. Ok, so the thread
fills up a data store. And the form must poll the data store to see
if it's changed, and then update. I see.

Zytan

May 28 '07 #17

P: n/a
On Mon, 28 May 2007 16:54:43 -0700, Zytan <zy**********@gmail.comwrote:
Oh, I didn't follow this is what you were saying. Ok, so the thread
fills up a data store. And the form must poll the data store to see
if it's changed, and then update. I see.
The form doesn't necessarily need to poll (in fact you should try to avoid
polling). You can still use some sort of inter-thread signaling to inform
the form that there is data to be retrieved. But the key is to have the
form initiate that, and remove itself from whatever signaling mechanism is
in place before it destroys itself.

Pete
May 29 '07 #18

P: n/a
The form doesn't necessarily need to poll (in fact you should try to avoid
polling).
I agree polling is bad.
You can still use some sort of inter-thread signaling to inform
the form that there is data to be retrieved.
Doesn't that bring the same problem as before? How can we signal the
form if we don't know if it exists or not?

Zytan

May 29 '07 #19

P: n/a
On Tue, 29 May 2007 06:19:03 -0700, Zytan <zy**********@gmail.comwrote:
>You can still use some sort of inter-thread signaling to inform
the form that there is data to be retrieved.

Doesn't that bring the same problem as before? How can we signal the
form if we don't know if it exists or not?
You can use the intermediate data structure to do the signaling, in a way
that relies on the form's own behavior to cause the signaling to do
anything. There are a variety of ways to do this.

For example, you could create a thread that the form controls that waits
on two events: one event signals new data, the other signals the thread to
stop trying to pull new data. This would require that the data queue
would have to publish (via a property or something) the waitable event it
uses.

You could use a single event if you allow the intermediate data structure
to know a little more about the consumer, and have it signal the event for
both purposes (with a flag or something indicating to the consumer to exit
rather than try to get more data...with a single consumer, this is easy,
with multiple consumers you'd have to have some sort of identification
scheme for each consumer).

Or you could use a .NET event (or similar mechanism...doesn't really have
to be an event) in which access to the event is synchronized, and the form
doesn't exit until it receives notification that it's been removed from
the event (depending on how you define the event, you could even just use
that event for signaling, with the queue class using the event one last
time to tell the form that it's been successfully removed from the event).

(Note that I use the word "event" in two different ways above...in the
first two cases, I'm talking about a waitable event, in the third case I'm
talking about a .NET event using the C# "event" keyword. Two *very*
different concepts).

I'm sure there's a variety of other ways, and frankly I think it's
possible that none of the above are really the *best* solution (it's not
like this is the sort of multi-threaded code I've had to deal with, so I
may be unaware of better built-in types of synchronization). But it seems
to me that any of the above would work.

I also am not sure that you couldn't just accomplish all of the above
using just the form and the network i/o code, but it seems to me that
having the intermediate class might make the separation of duties clearer
and easier to maintain.

Pete
May 29 '07 #20

P: n/a
(Note that I use the word "event" in two different ways above...in the
first two cases, I'm talking about a waitable event, in the third case I'm
talking about a .NET event using the C# "event" keyword. Two *very*
different concepts).
My lack of knowledge and comfort with events limits me from deciding
which of these methods is the best. They all seem rather
complicated. But, they all seem to be 'proper' solutions, where as
what I have now is sort of a hack.
I also am not sure that you couldn't just accomplish all of the above
using just the form and the network i/o code, but it seems to me that
having the intermediate class might make the separation of duties clearer
and easier to maintain.
Yes, and that's what I was hoping to avoid, but I can see that it's
quite complicated just to have a display of data that changes
constantly. Basically, having an intermediate class is the solution,
and once it's done, it could be reused easily. I don't currently have
a large need for this, though, and my simple hack is fine for now. I
wish I had the time to do this properly, but I don't.

Thanks for all of your help, it's been great.

Zytan

May 30 '07 #21

P: n/a
On Wed, 30 May 2007 07:42:15 -0700, Zytan <zy**********@gmail.comwrote:
My lack of knowledge and comfort with events limits me from deciding
which of these methods is the best. They all seem rather
complicated. But, they all seem to be 'proper' solutions, where as
what I have now is sort of a hack.
For what it's worth, you might as well learn about events. You already
are a client of events in your code if you're using .NET anyway, and while
I might be misusing them, the only thing I ran into that was a little
counter-intuitive was the need to copy the event used for subscribing to a
local variable before actually executing it.

Basically, an event looks a lot like a delegate in code; the main
difference is that when you "execute" an event, what really happens is
that all the delegates that have been subscribed to the event get executed
with the same parameter list (provided in the line that "executes" the
event).

In fact, in situations where you know you will only ever have a single
delegate subscribed, I suppose you could just use a delegate variable
instead of an event. The way the work is so similar, it'd be hard to
notice the difference. :)

You may not want to use them here, but there's really no reason to be
scared of learning them. They are a pretty straight-forward concept.

Note: in the above I am talking about the .NET "event", not the wait
handle type "event".

Pete
May 30 '07 #22

P: n/a
Basically, an event looks a lot like a delegate in code; the main
difference is that when you "execute" an event, what really happens is
that all the delegates that have been subscribed to the event get executed
with the same parameter list (provided in the line that "executes" the
event).
So, it's just as if I had an array of function pointers, and I called
each one of them. And they are subscribed to the event by adding
themselves in this array.
In fact, in situations where you know you will only ever have a single
delegate subscribed, I suppose you could just use a delegate variable
instead of an event. The way the work is so similar, it'd be hard to
notice the difference. :)
Yes.
You may not want to use them here, but there's really no reason to be
scared of learning them. They are a pretty straight-forward concept.
Yes, it's a very simple concept.

Zytan

Jun 2 '07 #23

This discussion thread is closed

Replies have been disabled for this discussion.