473,606 Members | 2,115 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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

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
22 3067
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.co m
"Zytan" <zy**********@g mail.comwrote in message
news:11******** **************@ u36g2000prd.goo glegroups.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
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.Invo keRequired, to see if the UI
thread is running the method. If it isn't, I'll make it run it, using
MyDataForm.Begi nInvoke.

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
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.Invo keRequired, to see if the UI
thread is running the method. If it isn't, I'll make it run it, using
MyDataForm.Begi nInvoke.

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.co m
May 22 '07 #4
On Tue, 22 May 2007 13:10:55 -0700, Zytan <zy**********@g mail.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...obviou sly 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.Invo keRequired, to see if the UI
thread is running the method. If it isn't, I'll make it run it, using
MyDataForm.Begi nInvoke.
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
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
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
On Sat, 26 May 2007 12:32:49 -0700, Zytan <zy**********@g mail.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
On Sat, 26 May 2007 12:48:19 -0700, Zytan <zy**********@g mail.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
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

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
73199
by: RAJ | last post by:
hi plz tell me how to know "how window is going to close"... i have to right code for X button of forms... plz telll me thanks bye
6
3222
by: Gary Miller | last post by:
Does anyone know how to detect a modeless form on closing by the form that invoked the modeless form? form.Show();
6
4085
by: nadeem_far | last post by:
Hello All, I am working on a .Net desktop application and I am having problem displaying a form. I am using C# and version 1.1 of the framework. here is how the code looks likes and I will appreciate if someone can tell me how to resolve this problem. Main ( Args ) { Form1 f1 = new Form1();
21
1681
by: SamSpade | last post by:
I declare a variable X of type myForm then instantiate myForm saving a reference in the variable X, and then do X.Show. If I need to know if the form has been shown yet, I check X against Nothing. If the users closes MyForm I'd like X to be set to Nothing but don't know how to sense (except in MyForm) that myForm is closing. In the myForm's Closing event if I set Me=Nothing will that set X to Nothing?
7
5223
by: Boni | last post by:
Dear all, if I do myform.close() is it disposed or not? is it correct do following? myForm.close() Info=SomeControlOntheForm.text This seems to work. But am not sure that it is waterproof. Thanks, Boni
5
3922
by: ortaias | last post by:
I have a form which calls up a second form for purposes of data entry. When closing the data entry form and returning to the main form, things don't work as expected. When I return to the main form, I trigger the on acitvate event to run a macro. I can use the Dlookup function to update my fields, which is OK. However, I intitially tried to use the Repaint Object command to repaint the form. That did not work. Though I solved the...
3
7687
by: Darin | last post by:
I have a problem I just can't figure out. I have a form with a subform, and the recordsource of the subform has criteria based on some unbound fields in the parent form so that data in the parent form affects data in the subform. I've had this type of setup often, but I've run across a couple forms where this has caused an "enter parameter value" pop up for each reference to the parent control in the query when the main form is closed. ...
0
252
by: Zytan | last post by:
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. ...
8
2014
by: AAaron123 | last post by:
If I show a form with ShowDialog and Dispose it FormClosing does not appear to run. At least I think that is true. If I want FormClosing and FormClose to run am I suppose to call the forms Close method?
0
8009
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8428
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8078
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8299
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
6753
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5456
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
3919
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
3964
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2442
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.