|
ms
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Dispose(bool), Idisposable, form closing etc.I am confused by dispose etc. and hope someone can set me right. 1. The Dispose(Bool) the IDE generates for a form has nothing to do with IDisposable, right? 2. So when is this called? When a form is closed? If this is caused automatically when a form is closed how can I then access things on a modal from after ShowDialog() returns? Or is it only for modeless forms? 3. Does the garbage collector automically call Dispose() which is part of IDisposable when an onbject is garbage collected? I know this is non-deterministic etc. Is this what is known as the Finalizer or whatever it's called? 4. I don't understand how garbage collection works with forms. If I have a method which declares a variable which is a form, and instantiate it in the same routine, when I leave the routine the variable is released, the form's reference count should then be zero and therefore a candiate for garbage collection, no? Is there another refernce to it somewhere? Confused, Ray Ray,
See inline: > 1. The Dispose(Bool) the IDE generates for a form has nothing to do Well, in a roundabout way, it does. The implementation of the Dispose > with IDisposable, right? method on the form class Form will call the override that is defined in your subclass (the Dispose(bool) implementation). > 2. So when is this called? When a form is closed? If this is caused It is called when a form is closed and it is not a modal form, yes. > automatically when a form is closed how can I then access things on a > modal from after ShowDialog() returns? Or is it only for modeless > forms? When showing the form modally, it doesn't dispose the form until Dispose is called on it (if you click the X button, it doesn't dispose yet, it just hides it). From the documentation from the ShowDialog method: When a form is displayed as a modal dialog box, clicking the Close button (the button with an X at the upper-right corner of the form) causes the form to be hidden and the DialogResult property to be set to DialogResult.Cancel. Unlike modeless forms, the Close method is not called by the .NET Framework when the user clicks the close form button of a dialog box or sets the value of the DialogResult property. Instead the form is hidden and can be shown again without creating a new instance of the dialog box. Because a form displayed as a dialog box is not closed, you must call the Dispose method of the form when the form is no longer needed by your application. In this case, you would do something like this: using (MyForm myForm = new MyForm()) { // Show it. if (myForm.ShowDialog() = <whatever you want to compare to>) ... } > 3. Does the garbage collector automically call Dispose() which is part Well, if Dispose is not called on the form (directly or indirectly) then > of IDisposable when an onbject is garbage collected? I know this is > non-deterministic etc. Is this what is known as the Finalizer or > whatever it's called? when the form has no more references to it, and it is garbage collected, Dispose is called. > 4. I don't understand how garbage collection works with forms. If I There is no actual reference count, per se, but all the reference to the > have a method which declares a variable which is a form, and > instantiate it in the same routine, when I leave the routine the > variable is released, the form's reference count should then be zero > and therefore a candiate for garbage collection, no? Is there another > refernce to it somewhere? form are gone, so yes, it is a candidate for GC. This assumes you didn't pass the reference outside of the method, or assigned it to some field elsewhere which is keeping the object alive. -- Show quote- Nicholas Paldino [.NET/C# MVP] - mvp@spam.guard.caspershouse.com > > Confused, > > Ray > On 19 Nov, 20:32, "Nicholas Paldino [.NET/C# MVP]"
<m...@spam.guard.caspershouse.com> wrote: Show quote > Ray, Thank you all for replying I've arbitrarily chosen yours to reply to,> > See inline: > > > 1. TheDispose(Bool) the IDE generates for a form has nothing to do > > with IDisposable, right? > > Well, in a roundabout way, it does. The implementation of theDispose > method on the form class Form will call the override that is defined in your > subclass (theDispose(bool) implementation). > > > 2. So when is this called? When a form is closed? If this is caused > > automatically when a form is closed how can I then access things on a > > modal from after ShowDialog() returns? Or is it only for modeless > > forms? > > It is called when a form is closed and it is not a modal form, yes. > When showing the form modally, it doesn'tdisposethe form untilDisposeis > called on it (if you click the X button, it doesn'tdisposeyet, it just > hides it). From the documentation from the ShowDialog method: > When a form is displayed as a modal dialog box, clicking the Close button > (the button with an X at the upper-right corner of the form) causes the form > to be hidden and the DialogResult property to be set to DialogResult.Cancel. > Unlike modeless forms, the Close method is not called by the .NET Framework > when the user clicks the close form button of a dialog box or sets the value > of the DialogResult property. Instead the form is hidden and can be shown > again without creating a new instance of the dialog box. Because a form > displayed as a dialog box is not closed, you must call theDisposemethod of > the form when the form is no longer needed by your application. > > In this case, you would do something like this: > > using (MyForm myForm = new MyForm()) > { > // Show it. > if (myForm.ShowDialog() = <whatever you want to compare to>) > ... > > } > > 3. Does the garbage collector automically callDispose() which is part > > of IDisposable when an onbject is garbage collected? I know this is > > non-deterministic etc. Is this what is known as the Finalizer or > > whatever it's called? > > Well, ifDisposeis not called on the form (directly or indirectly) then > when the form has no more references to it, and it is garbage collected,Disposeis called. > > > 4. I don't understand how garbage collection works with forms. If I > > have a method which declares a variable which is a form, and > > instantiate it in the same routine, when I leave the routine the > > variable is released, the form's reference count should then be zero > > and therefore a candiate for garbage collection, no? Is there another > > refernce to it somewhere? > > There is no actual reference count, per se, but all the reference to the > form are gone, so yes, it is a candidate for GC. This assumes you didn't > pass the reference outside of the method, or assigned it to some field > elsewhere which is keeping the object alive. > > -- > - Nicholas Paldino [.NET/C# MVP] > - m...@spam.guard.caspershouse.com > > > > > > > Confused, > > > Ray- Hide quoted text - > > - Show quoted text - Nicholas. So let me see if I have this right: 1. Dispose(Bool) as part of a form is not explicitly part of the IDisposable interface, but the implementation of IDisposable,Dispose further up the class hierarchy (form I suppose) calls this. This is waht Brian called the Canonical implementation (I never did understand what that word meant!). 2, When a modeless form is called, clicking the form's close button, or calling the close() method calls IDisposable.Dispose which in turn calls Dispose(bool). 3. If it's a modal form, clicking the close button or calling the close method just hides the form, and does not call IDisposable.dispose. Therefore I have to do it myself or use a Using clause. 4. A form's destructor will call Dispose(bool) although in most cases it will not do much because it will already have been called by IDisposable.dispose. SO...I'm guessing that Idisposable calls dispose(true), whereas the destructor calls Dispose(false)? 5. With regard to garbage collecting - doesn't Peter have it correct where he says the form is not garbage collected because it is referenced by application.openForms? 6. Brian mentioned that some class authors write property getters to return data even after the form has been destroyed - I don't understand this. Doesn't this mean the property getter has to be static - and where would it savbe the data? In static class vars? That implies I only have one instance of the form, right? Thanks everbody, Best Ray "rbrowning1958" <RBrowning1***@gmail.com> wrote in message I'm just guessing here but I'd imagine that application.openForms keeps what news:db58258c-fe2b-40f2-be53-9b5c2f979a5c@41g2000hsh.googlegroups.com... > 5. With regard to garbage collecting - doesn't Peter have it correct > where he says the form is not garbage collected because it is > referenced by application.openForms? is called a weak reference to the form. This means that if all other references are dropped then the GC can kill the references in openForms. > 6. Brian mentioned that some class authors write property getters to No, they are instance members. Remember the form is only hidden so > return data even after the form has been destroyed - I don't > understand this. Doesn't this mean the property getter has to be > static - and where would it savbe the data? In static class vars? That > implies I only have one instance of the form, right? everything can be accessed still Michael On 2007-11-20 15:50:15 -0800, "Michael C" <mike@nospam.com> said: No, that's not true. If it were, forms applications would be in a > "rbrowning1958" <RBrowning1***@gmail.com> wrote in message > news:db58258c-fe2b-40f2-be53-9b5c2f979a5c@41g2000hsh.googlegroups.com... >> 5. With regard to garbage collecting - doesn't Peter have it correct >> where he says the form is not garbage collected because it is >> referenced by application.openForms? > > I'm just guessing here but I'd imagine that application.openForms keeps what > is called a weak reference to the form. This means that if all other > references are dropped then the GC can kill the references in openForms. world of hurt. After all, they by default all start out like this: void Main() { ... Application.Run(new Form1()); } At a minimum, in the Run() method, there'd have to be some strong reference to the parameter passed in. But more significantly, this sort of code: void button1_Click(object sender, EventArgs e) { Form2 form2 = new Form2(); form2.Show(); } which is quite common, would never work if what you say is true. No, I believe that the list that is exposed as Application.OpenForms is a list of plain old strong references. The application code itself is not required to maintain a reference, so there must be a strong reference somewhere else and the underlying list implementing OpenForms is the most likely source. Now that VS2008 is out, it's only a matter of time before you can go look yourself if you don't believe me. :) In the meantime, you could get Reflector and look at the implementation. I've never tried it myself, but I'm confident at what I might find should I try. Weak references just wouldn't do the job. Pete On Nov 20, 5:21 am, rbrowning1958 <RBrowning1***@gmail.com> wrote:
> 1. Dispose(Bool) as part of a form is not explicitly part of the I used the word canonical to mean an authorized, well-established> IDisposable interface, but the implementation of IDisposable,Dispose > further up the class hierarchy (form I suppose) calls this. This is > waht Brian called the Canonical implementation (I never did understand > what that word meant!). > pattern. Show quote > 2, When a modeless form is called, clicking the form's close button, I don't think I was very clear. What I meant was that you may still> or calling the close() method calls IDisposable.Dispose which in turn > calls Dispose(bool). > > 3. If it's a modal form, clicking the close button or calling the > close method just hides the form, and does not call > IDisposable.dispose. Therefore I have to do it myself or use a Using > clause. > > 4. A form's destructor will call Dispose(bool) although in most cases > it will not do much because it will already have been called by > IDisposable.dispose. SO...I'm guessing that Idisposable calls > dispose(true), whereas the destructor calls Dispose(false)? > > 5. With regard to garbage collecting - doesn't Peter have it correct > where he says the form is not garbage collected because it is > referenced by application.openForms? > > 6. Brian mentioned that some class authors write property getters to > return data even after the form has been destroyed - I don't > understand this. Doesn't this mean the property getter has to be > static - and where would it savbe the data? In static class vars? That > implies I only have one instance of the form, right? > be able to call some property getters without them throwing exceptions even after Dispose has been called on the object. That's because property getters are usually nothing more than trivial wrappers around instance variables. "Peter Duniho" <NpOeStPe***@NnOwSlPiAnMk.com> wrote in message news:2007112017431716807-NpOeStPeAdM@NnOwSlPiAnMkcom...> No, that's not true. If it were, forms applications would be in a world That wouldn't be a problem because application.Run would keep a reference. > of hurt. After all, they by default all start out like this: > > void Main() > { > ... > Application.Run(new Form1()); > } Although you're probably right about everything else. I guess the form must remove itself from the collection at some point. Michael
Show quote
On 2007-11-20 19:52:36 -0800, "Michael C" <mike@nospam.com> said: How do you know?> "Peter Duniho" <NpOeStPe***@NnOwSlPiAnMk.com> wrote in message > news:2007112017431716807-NpOeStPeAdM@NnOwSlPiAnMkcom... >> No, that's not true. If it were, forms applications would be in a world >> of hurt. After all, they by default all start out like this: >> >> void Main() >> { >> ... >> Application.Run(new Form1()); >> } > > That wouldn't be a problem because application.Run would keep a reference. I did write that it _could_ keep a reference. But there's no obvious reason it should. For example, what if it looked something like this: void Run(Form form) { // some code to add the form instance to the open forms list // past this point, the variable "form" is never used // then a message pump loop here while (GetAMessage() != null) { // translate the message // dispatch the message } } (note that I have no idea what the message pump loop actually looks like...the above should suffice for this purpose though :) ) In the above example, the "form" parameter is no longer considered a reference to the instance once the message pump loop is entered, the last use of the variable having been prior to that point. Yes, you could fix it by adding a GC.KeepAlive(form) at the end of the method, but that seems sort of silly to do, especially since the issue would still exist for other code that instantiates a form, shows it, and then doesn't keep a copy of the reference anywhere. > Although you're probably right about everything else. I guess the form must I'm sure that when the form is actually disposed, it removes itself > remove itself from the collection at some point. from the open forms list. Assuming this is true, it's also a highlight as to why it's so important to dispose forms shown modally when you're done with them. For many managed types that implement IDisposable, if you forget to dispose them eventually it's likely that the finalizer will catch up and go ahead and do that work for you. But if a form isn't removed from the open forms list until it's disposed, and a form isn't eligible for garbage collection until it's removed from the open forms list, then a modal form that you don't dispose will _never_ be garbage collected. It's a very serious resource leak, much more so than the usual "didn't dispose" kind of bug. Though, I admit I don't really know the details. Now I'm curious, so if I get a moment I'll actually test it and see if I can figure out what's going on. The bottom line, however, is that you do not need to keep a reference to an open form in order to prevent it from being collected. The framework is keeping a strong reference itself, ensuring the form sticks around as long as it needs to. Pete "Peter Duniho" <NpOeStPe***@NnOwSlPiAnMk.com> wrote in message news:2007112020062211272-NpOeStPeAdM@NnOwSlPiAnMkcom...> In the above example, the "form" parameter is no longer considered a I just gave it a test and the reference remains valid until the function > reference to the instance once the message pump loop is entered, the last > use of the variable having been prior to that point. exists. So unless they actually set it not null (which I doubt) then it would remain a reference. > The bottom line, however, is that you do not need to keep a reference to I wonder how it did all this before the forms collection existed.> an open form in order to prevent it from being collected. The framework > is keeping a strong reference itself, ensuring the form sticks around as > long as it needs to. Show quote > > Pete > On 2007-11-20 20:21:26 -0800, "Michael C" <mike@nospam.com> said: That doesn't tell you anything. As long as the reference is in the > "Peter Duniho" <NpOeStPe***@NnOwSlPiAnMk.com> wrote in message > news:2007112020062211272-NpOeStPeAdM@NnOwSlPiAnMkcom... >> In the above example, the "form" parameter is no longer considered a >> reference to the instance once the message pump loop is entered, the last >> use of the variable having been prior to that point. > > I just gave it a test and the reference remains valid until the function > exists. So unless they actually set it not null (which I doubt) then it > would remain a reference. open forms list (and of course it would be), the fact that the reference remains valid until the function exits is meaningless. In fact, it's a given that the reference to the form would remain valid until Application.Run() returns, because if that weren't true a forms application would never work. By definition, the method returns when the form is closed, so obviously the duration of the call to Application.Run() and the lifetime of the form are _very_ closely tied to each other. In other words, whatever test you did, all it accomplished was proving that Application.Run() does in fact work. Which hopefully we all believed already. >> The bottom line, however, is that you do not need to keep a reference to There's no reason to believe that the collection of forms didn't exist >> an open form in order to prevent it from being collected. The framework >> is keeping a strong reference itself, ensuring the form sticks around as >> long as it needs to. > > I wonder how it did all this before the forms collection existed. before. Just because it wasn't exposed to the application itself, that doesn't mean it wasn't there. Pete "Peter Duniho" <NpOeStPe***@NnOwSlPiAnMk.com> wrote in message news:2007112020512427544-NpOeStPeAdM@NnOwSlPiAnMkcom...> That doesn't tell you anything. As long as the reference is in the open No, I gave it a test with a regular class. The class would not be collected > forms list (and of course it would be), the fact that the reference > remains valid until the function exits is meaningless. until the function exited. > I wasn't talking about Application.Run at all. I was just using a regular > In fact, it's a given that the reference to the form would remain valid > until Application.Run() returns, because if that weren't true a forms > application would never work. By definition, the method returns when the > form is closed, so obviously the duration of the call to Application.Run() > and the lifetime of the form are _very_ closely tied to each other. function that I defined myself and passed in an instance of a class I defined. The only way I could get the class to be GCd before the function exits was to set the parameter to null inside the function. > In other words, whatever test you did, all it accomplished was proving Rubbish.> that Application.Run() does in fact work. Which hopefully we all believed > already. > There's no reason to believe that the collection of forms didn't exist That's true although that doesn't mean it did exist either.> before. Just because it wasn't exposed to the application itself, that > doesn't mean it wasn't there. Michael
Show quote
On 21 Nov, 04:58, "Michael C" <m...@nospam.com> wrote: Michael,> "Peter Duniho" <NpOeStPe***@NnOwSlPiAnMk.com> wrote in message > > news:2007112020512427544-NpOeStPeAdM@NnOwSlPiAnMkcom... > > > That doesn't tell you anything. As long as the reference is in the open > > forms list (and of course it would be), the fact that the reference > > remains valid until the function exits is meaningless. > > No, I gave it a test with a regular class. The class would not be collected > until the function exited. > > > > > In fact, it's a given that the reference to the form would remain valid > > until Application.Run() returns, because if that weren't true a forms > > application would never work. By definition, the method returns when the > > form is closed, so obviously the duration of the call to Application.Run() > > and the lifetime of the form are _very_ closely tied to each other. > > I wasn't talking about Application.Run at all. I was just using a regular > function that I defined myself and passed in an instance of a class I > defined. The only way I could get the class to be GCd before the function > exits was to set the parameter to null inside the function. > > > In other words, whatever test you did, all it accomplished was proving > > that Application.Run() does in fact work. Which hopefully we all believed > > already. > > Rubbish. > > > There's no reason to believe that the collection of forms didn't exist > > before. Just because it wasn't exposed to the application itself, that > > doesn't mean it wasn't there. > > That's true although that doesn't mean it did exist either. > > Michael What I've found is that showing a form adds itself to application.openForms, but hiding a modeless form does not remove it. Surely the reason this works with Application.run is because that shows the form, hence its referenced by application.openForms. Hiding a modeless form doess seem to remove it from application.openForms which kind of makes sense because closing it does not dispose it therefore it needs to be removed from application.forms so it can be a candidate for GC. Ray On 2007-11-20 20:58:15 -0800, "Michael C" <mike@nospam.com> said: That's not a test of Application.Run().> "Peter Duniho" <NpOeStPe***@NnOwSlPiAnMk.com> wrote in message > news:2007112020512427544-NpOeStPeAdM@NnOwSlPiAnMkcom... >> That doesn't tell you anything. As long as the reference is in the open >> forms list (and of course it would be), the fact that the reference >> remains valid until the function exits is meaningless. > > No, I gave it a test with a regular class. The class would not be collected > until the function exited. > I wasn't talking about Application.Run at all. I was just using a regular It is well-known and documented that a reference held only by a > function that I defined myself and passed in an instance of a class I > defined. The only way I could get the class to be GCd before the function > exits was to set the parameter to null inside the function. variable that is no longer used is eligible for garbage collection even while the variable is in scope. It's why GC.KeepAlive() even exists. If you were unable to reproduce that behavior, it only means your test was flawed. >> In other words, whatever test you did, all it accomplished was proving You don't believe that Application.Run() does in fact work?>> that Application.Run() does in fact work. Which hopefully we all believed >> already. > > Rubbish. >> There's no reason to believe that the collection of forms didn't exist It's easier to believe that it did exist. What is your alternative >> before. Just because it wasn't exposed to the application itself, that >> doesn't mean it wasn't there. > > That's true although that doesn't mean it did exist either. theory to explain why even prior to .NET 2.0 you could create a form instance and have the form remain uncollected even though the only variable referencing the form goes out of scope? Pete On 2007-11-20 23:32:39 -0800, Peter Duniho <NpOeStPe***@NnOwSlPiAnMk.com> said:
>> [...] Okay, my apologies on this point.>> I wasn't talking about Application.Run at all. I was just using a regular >> function that I defined myself and passed in an instance of a class I >> defined. The only way I could get the class to be GCd before the function >> exits was to set the parameter to null inside the function. > > It is well-known and documented that a reference held only by a > variable that is no longer used is eligible for garbage collection even > while the variable is in scope. It's why GC.KeepAlive() even exists. > > If you were unable to reproduce that behavior, it only means your test > was flawed. I still say that unless you look at Application.Run(), you can't really say for sure what it's doing. It could in fact set the parameter to null after adding the reference to the list of open forms (by showing the form). Why it would, I don't know...seems like an odd thing to do, but then I've seen some seemingly odd code in Windows (though usually it was only "odd" because I didn't understand the need for it). However, you're right that parameters are treated differently from local variables, and as long as the parameter references the instance for the duration of the call to the method, the instance won't be collected. I'm (obviously) a little surprised that parameters aren't treated the same as local variables. I wonder if there's some subtle difference in the behavior of a parameter I'm unaware of. At least for parameters passed by value, I generally view them just like local variables except that the caller gets to initialize them. But here's one example where they definitely don't behave like a local variable. Pete On Nov 21, 2:16 am, Peter Duniho <NpOeStPe***@NnOwSlPiAnMk.com> wrote:
> I don't know if I'm convinced of that. You may have been right the> [snip] > > However, you're right that parameters are treated differently from > local variables, and as long as the parameter references the instance > for the duration of the call to the method, the instance won't be > collected. > > [snip] first time. What made you change your mind? Is there a section in the CLI specification that talks about this? Obviously, a parameter can be collected during the execution of an unmanaged function. That's the most important reason for the existence of GC.KeepAlive. But, I want to know if a parameter can be collected before the completion of a managed function. I haven't seen conclusive documentation that guarentees that it won't. In fact, I don't see any reason why the runtime couldn't support that optimization. Comments? On 2007-11-21 08:07:02 -0800, Brian Gideon <briangid***@yahoo.com> said:
Show quote > On Nov 21, 2:16 am, Peter Duniho <NpOeStPe***@NnOwSlPiAnMk.com> wrote: I wrote a test myself. And just like Michael said, while I could >> >> [snip] >> >> However, you're right that parameters are treated differently from >> local variables, and as long as the parameter references the instance >> for the duration of the call to the method, the instance won't be >> collected. >> >> [snip] > > I don't know if I'm convinced of that. You may have been right the > first time. What made you change your mind? Is there a section in > the CLI specification that talks about this? easily reproduce early collection for an object referenced by a local variable, I could not get it to happen with an object referenced only by a parameter. Granted, it's not really a scientifically valid proof. Lack of behavior isn't proof. But it's pretty compelling. It is possible that the CLI _allows_ for early collection of parameter-held references, and that the current implementation itself just doesn't take advantage of that. But if so, the behavior is (I think) more important than the theoretical possibility in this case, since we're talking about what Application.Run() _does_, not what it might do. > Obviously, a parameter can be collected during the execution of an Based on what I've seen, I'm not convinced of that. Even when there's > unmanaged function. no actual use of the parameter in a method, the object referenced by it is apparently not collectable until the method returns. It wouldn't matter whether you called a managed or unmanaged function. > That's the most important reason for the I'm not sure I'd rank the reasons in that way, but I'm not willing to > existence of GC.KeepAlive. quibble about which is the _most_ important. Clearly you need GC.KeepAlive() any time you need to avoid early collection of references that aren't explicitly used later in the method. There are lots of different ways to run into the issue, and calling an unmanaged function is just one example. But if you want that to be the most important, that's okay by me. :) > But, I want to know if a parameter can be I'm not aware of any guarantee that it won't either. I can just say > collected before the completion of a managed function. I haven't seen > conclusive documentation that guarentees that it won't. In fact, I > don't see any reason why the runtime couldn't support that > optimization. Comments? that I tried very hard to get it to happen and was unable to. Pete On Nov 21, 12:26 pm, Peter Duniho <NpOeStPe***@NnOwSlPiAnMk.com>
wrote: > It is possible that the CLI _allows_ for early collection of Maybe. I'm just thinking about theoretical possibilities that I could> parameter-held references, and that the current implementation itself > just doesn't take advantage of that. But if so, the behavior is (I > think) more important than the theoretical possibility in this case, > since we're talking about what Application.Run() _does_, not what it > might do. not demonstrate in 1.1, but were a piece of cake in 2.0. At some level you have to consider the possibility or risk hard to find bugs when your code runs on a newer version of the framework. > Yeah, after some more thought I think you're right. The interop> > Obviously, a parameter can be collected during the execution of an > > unmanaged function. > > Based on what I've seen, I'm not convinced of that. Even when there's > no actual use of the parameter in a method, the object referenced by it > is apparently not collectable until the method returns. It wouldn't > matter whether you called a managed or unmanaged function. > marshaler would likely prevent the reference from being eligible until the function returns. Asynchronous functions and functions that accept say...an IntPtr to a managed object would still be problematic. > > That's the most important reason for the No, you are right. I should be careful about ranking things like> > existence of GC.KeepAlive. > > I'm not sure I'd rank the reasons in that way, but I'm not willing to > quibble about which is the _most_ important. Clearly you need > GC.KeepAlive() any time you need to avoid early collection of > references that aren't explicitly used later in the method. There are > lots of different ways to run into the issue, and calling an unmanaged > function is just one example. > > But if you want that to be the most important, that's okay by me. :) > that. There certainly are other reasons for it's use. A scenario involving an unmanaged function just happened to be the only time I've used it :) "Brian Gideon" <briangid***@yahoo.com> wrote in message I just tested this because I was pretty sure you were wrong but you are in news:5ac95686-8715-451f-a0d7-b7b8744db726@g30g2000hsb.googlegroups.com... >> Based on what I've seen, I'm not convinced of that. Even when there's >> no actual use of the parameter in a method, the object referenced by it >> is apparently not collectable until the method returns. It wouldn't >> matter whether you called a managed or unmanaged function. >> > > Yeah, after some more thought I think you're right. The interop > marshaler would likely prevent the reference from being eligible until > the function returns. Asynchronous functions and functions that > accept say...an IntPtr to a managed object would still be problematic. fact correct. When passing an instance of a class into an unmanaged function I couldn't get it to dispose of the object while it was in the function. Code is below if you want to test. C++ code: #include "stdafx.h" #include "DelMeDll.h" BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } typedef int __stdcall SomeCallback(int Count); // This is an example of an exported function. int __stdcall DoIt(void* CallbackPtr, void* SomeClass) { SomeCallback* sc = (SomeCallback*)CallbackPtr; for(int i = 0; i < 10; i++) { sc(i); } return 42; } C# code using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Runtime.InteropServices; namespace DelMeCallDLL { public delegate int CallbackDelegate(int Count); public class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.Button button2; private System.Windows.Forms.Button button1; [DllImport("C:\\Stuff\\DelMeDll\\Debug\\DelMeDll.dll")] static extern int DoIt(CallbackDelegate CallBack, SomeClass MyClass); public Form1() { InitializeComponent(); } #region Windows Form Designer generated code private void InitializeComponent() { this.button1 = new System.Windows.Forms.Button(); this.button2 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // button1 // this.button1.Location = new System.Drawing.Point(104, 80); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(80, 80); this.button1.TabIndex = 0; this.button1.Text = "button1"; this.button1.Click += new System.EventHandler(this.button1_Click); // // button2 // this.button2.Location = new System.Drawing.Point(192, 208); this.button2.Name = "button2"; this.button2.Size = new System.Drawing.Size(64, 48); this.button2.TabIndex = 1; this.button2.Text = "button2"; this.button2.Click += new System.EventHandler(this.button2_Click); // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(292, 266); this.Controls.Add(this.button2); this.Controls.Add(this.button1); this.Name = "Form1"; this.Text = "Form1"; this.ResumeLayout(false); } #endregion [STAThread] static void Main() { Application.Run(new Form1()); } private void button1_Click(object sender, System.EventArgs e) { DoIt(new CallbackDelegate(this.Callback), new SomeClass()); } private int Callback(int Count) { GC.Collect(); Console.WriteLine(Count.ToString()); return Count; } private void button2_Click(object sender, System.EventArgs e) { GC.Collect(); } } } On 21 Nov, 03:18, Brian Gideon <briangid***@yahoo.com> wrote:
Show quote > On Nov 20, 5:21 am,rbrowning1958<RBrowning1***@gmail.com> wrote: Clear - thanks. I was confused Re the values in the components which> > > 1. Dispose(Bool) as part of a form is not explicitly part of the > > IDisposable interface, but the implementation of IDisposable,Dispose > > further up the class hierarchy (form I suppose) calls this. This is > > waht Brian called the Canonical implementation (I never did understand > > what that word meant!). > > I used the word canonical to mean an authorized, well-established > pattern. > > > > > > > 2, When a modeless form is called, clicking the form's close button, > > or calling the close() method calls IDisposable.Dispose which in turn > > calls Dispose(bool). > > > 3. If it's a modal form, clicking the close button or calling the > > close method just hides the form, and does not call > > IDisposable.dispose. Therefore I have to do it myself or use a Using > > clause. > > > 4. A form's destructor will call Dispose(bool) although in most cases > > it will not do much because it will already have been called by > > IDisposable.dispose. SO...I'm guessing that Idisposable calls > > dispose(true), whereas the destructor calls Dispose(false)? > > > 5. With regard to garbage collecting - doesn't Peter have it correct > > where he says the form is not garbage collected because it is > > referenced by application.openForms? > > > 6. Brian mentioned that some class authors write property getters to > > return data even after the form has been destroyed - I don't > > understand this. Doesn't this mean the property getter has to be > > static - and where would it savbe the data? In static class vars? That > > implies I only have one instance of the form, right? > > I don't think I was very clear. What I meant was that you may still > be able to call some property getters without them throwing exceptions > even after Dispose has been called on the object. That's because > property getters are usually nothing more than trivial wrappers around > instance variables.- Hide quoted text - > > - Show quoted text - would be destroyed by dispose(bool) versus simple instance vars which are freed when the form is garbage collected. We tend to use the word destroy for both things which is a bit confusing. Ta Ray On 21 Nov, 18:26, Peter Duniho <NpOeStPe***@NnOwSlPiAnMk.com> wrote:
Show quote > On 2007-11-21 08:07:02 -0800, Brian Gideon <briangid***@yahoo.com> said: Pete and Brian,> > > On Nov 21, 2:16 am, Peter Duniho <NpOeStPe***@NnOwSlPiAnMk.com> wrote: > > >> [snip] > > >> However, you're right that parameters are treated differently from > >> local variables, and as long as the parameter references the instance > >> for the duration of the call to the method, the instance won't be > >> collected. > > >> [snip] > > > I don't know if I'm convinced of that. You may have been right the > > first time. What made you change your mind? Is there a section in > > the CLI specification that talks about this? > > I wrote a test myself. And just like Michael said, while I could > easily reproduce early collection for an object referenced by a local > variable, I could not get it to happen with an object referenced only > by a parameter. > > Granted, it's not really a scientifically valid proof. Lack of > behavior isn't proof. But it's pretty compelling. > > It is possible that the CLI _allows_ for early collection of > parameter-held references, and that the current implementation itself > just doesn't take advantage of that. But if so, the behavior is (I > think) more important than the theoretical possibility in this case, > since we're talking about what Application.Run() _does_, not what it > might do. > > > Obviously, a parameter can be collected during the execution of an > > unmanaged function. > > Based on what I've seen, I'm not convinced of that. Even when there's > no actual use of the parameter in a method, the object referenced by it > is apparently not collectable until the method returns. It wouldn't > matter whether you called a managed or unmanaged function. > > > That's the most important reason for the > > existence of GC.KeepAlive. > > I'm not sure I'd rank the reasons in that way, but I'm not willing to > quibble about which is the _most_ important. Clearly you need > GC.KeepAlive() any time you need to avoid early collection of > references that aren't explicitly used later in the method. There are > lots of different ways to run into the issue, and calling an unmanaged > function is just one example. > > But if you want that to be the most important, that's okay by me. :) > > > But, I want to know if a parameter can be > > collected before the completion of a managed function. I haven't seen > > conclusive documentation that guarentees that it won't. In fact, I > > don't see any reason why the runtime couldn't support that > > optimization. Comments? > > I'm not aware of any guarantee that it won't either. I can just say > that I tried very hard to get it to happen and was unable to. > > Pete I'm not familiar with the difference between a weak and a strong reference. The way my simple mind works would lead me to believe that a form's constructor adds itself to the application.openForms list, and the dispose(bool) thing would remove it from that list, making it eligible for garbage collection as long as nothing else references the form. Since application.run is instantiating a form then its constructor adds it to applcation,openforms thereby keeping it alive even if there is no other variable referencing it. Am I missing something? Ta Ray On 2007-11-26 05:55:53 -0800, rbrowning1958 <RBrowning1***@gmail.com> said:
> I'm not familiar with the difference between a weak and a strong You don't really need to be. As far as garbage collection is > reference. concerned, a weak reference isn't a reference at all, while a strong reference is just a normal reference like what you're accustomed to. > The way my simple mind works would lead me to believe that That's not quite correct. A form is added to the open forms list when > a form's > constructor adds itself to the application.openForms list, and the > dispose(bool) thing would remove it from that list, making it eligible > for garbage collection as long as nothing else references the form. it's shown, and removed when it's hidden. Simply constructing the form doesn't add it, and it can be removed from the list without disposing the form. > Since application.run is instantiating a form then its constructor Application.Run() shows the form, and since it must maintaing the > adds it to applcation,openforms thereby keeping it alive even if there > is no other variable referencing it. Am I missing something? reference itself until that point, you're assured the GC won't collect the form before that point. After that point, the shown form is in the open forms list and thus also won't be collected. IMHO, the important thing here is that the system does work and forms won't be collected prematurely, assuming you use the normal idioms in ..NET. You can, of course, manage your forms in some obfuscated way that does manage to prematurely release a form, but you'd have to go out of your way to do that (for example, showing the form outside the normal Application.Run() mechanism, and storing the reference in a WeakReference instance). In any case, as long as the form is visible on the screen, it will not be collected. Pete On 26 Nov, 18:08, Peter Duniho <NpOeStPe***@NnOwSlPiAnMk.com> wrote:
Show quote > On 2007-11-26 05:55:53 -0800,rbrowning1958<RBrowning1***@gmail.com> said: Pete,> > > I'm not familiar with the difference between a weak and a strong > > reference. > > You don't really need to be. As far as garbage collection is > concerned, a weak reference isn't a reference at all, while a strong > reference is just a normal reference like what you're accustomed to. > > > The way my simple mind works would lead me to believe that > > a form's > > constructor adds itself to the application.openForms list, and the > > dispose(bool) thing would remove it from that list, making it eligible > > for garbage collection as long as nothing else references the form. > > That's not quite correct. A form is added to the open forms list when > it's shown, and removed when it's hidden. Simply constructing the form > doesn't add it, and it can be removed from the list without disposing > the form. > > > Since application.run is instantiating a form then its constructor > > adds it to applcation,openforms thereby keeping it alive even if there > > is no other variable referencing it. Am I missing something? > > Application.Run() shows the form, and since it must maintaing the > reference itself until that point, you're assured the GC won't collect > the form before that point. After that point, the shown form is in the > open forms list and thus also won't be collected. > > IMHO, the important thing here is that the system does work and forms > won't be collected prematurely, assuming you use the normal idioms in > .NET. You can, of course, manage your forms in some obfuscated way > that does manage to prematurely release a form, but you'd have to go > out of your way to do that (for example, showing the form outside the > normal Application.Run() mechanism, and storing the reference in a > WeakReference instance). > > In any case, as long as the form is visible on the screen, it will not > be collected. > > Pete <<That's not quite correct. A form is added to the open forms list when it's shown, and removed when it's hidden. Simply constructing the form doesn't add it, and it can be removed from the list without disposing the form.>> I don't think that's quite correct - but what do I know? What my tests show is that the form is not removed from application.openForms when a form is hidden. What's unusual though is it is not added to the openForms list until it is shown. If you create the form but don't display it it's not in the list. As soon as you show it it is added to the list and not removed until the form is closed (close method or clicking close button which I presume calls Dispose(bool)). I wonder what happens when you do this: Form2 form2; form2 = new Form2(); i.e. declare and instantiate inside a routine. It's probably a candidate for GC straight away - nothing references it and it's not visible. It's not disposed(bool) though is it? If I did show it it gets added to the application.forms list so there is a reference to it. So what's a "WeakReference instance"? Best Ray On 2007-11-28 06:39:13 -0800, rbrowning1958 <RBrowning1***@gmail.com> said:
> <<That's not quite correct. A form is added to the open forms list I should have been more precise, especially given that you can hide a > when > it's shown, and removed when it's hidden. Simply constructing the > form > doesn't add it, and it can be removed from the list without disposing > the form.>> > I don't think that's quite correct - but what do I know? What my tests > show is that the form is not removed from application.openForms when a > form is hidden. form without closing it. Closing a modal form doesn't dispose it; it just hides it. But doing so is still sufficient for it to be removed from the open forms list. But you're right, the important act is closing the form, not hiding it. > What's unusual though is it is not added to the Right. Noting that for modal forms closing the form doesn't dispose it.> openForms list until it is shown. If you create the form but don't > display it it's not in the list. As soon as you show it it is added to > the list and not removed until the form is closed (close method or > clicking close button which I presume calls Dispose(bool)). > I wonder That's correct.> what happens when you do this: > > Form2 form2; > form2 = new Form2(); > > i.e. declare and instantiate inside a routine. It's probably a > candidate for GC straight away - nothing references it and it's not > visible. > It's not disposed(bool) though is it? The finalizer will dispose it, eventually.> If I did show it it That's correct.> gets added to the application.forms list so there is a reference to > it. > So what's a "WeakReference instance"? WeakReference is a class. A WeakReference instance is an instance of that class. Pete "rbrowning1958" <RBrowning1***@gmail.com> schrieb im Newsbeitrag Dispose does not delete the instance. It only frees, what should not wait news:db58258c-fe2b-40f2-be53-9b5c2f979a5c@41g2000hsh.googlegroups.com... > > 6. Brian mentioned that some class authors write property getters to > return data even after the form has been destroyed - I don't > understand this. Doesn't this mean the property getter has to be > static - and where would it savbe the data? In static class vars? That > implies I only have one instance of the form, right? for the GC to be freed. The fields of the instance still live on, until the instance is collected. So any propertie, that does not depend on the 'open state' of the form will be accessible. This includes all properties that simply access fields. But, in case of a form, you can't access f.e. the controls of the form (or at least, you shouldn't count on). If the form is destroyed in the sense, that it is collected, than there is no reference to the instance left (if the GC worked right ;-) ), and so no member of the instance can be accessed. Christof
Show quote
On 20 Nov, 16:13, "Christof Nordiek" <c...@nospam.de> wrote: Hi Cristof,> "rbrowning1958" <RBrowning1***@gmail.com> schrieb im Newsbeitragnews:db58258c-fe2b-40f2-be53-9b5c2f979***@41g2000hsh.googlegroups.com... > > > > > 6. Brian mentioned that some class authors write property getters to > > return data even after the form has been destroyed - I don't > > understand this. Doesn't this mean the property getter has to be > > static - and where would it savbe the data? In static class vars? That > > implies I only have one instance of the form, right? > > Dispose does not delete the instance. It only frees, what should not wait > for the GC to be freed. The fields of the instance still live on, until the > instance is collected. So any propertie, that does not depend on the 'open > state' of the form will be accessible. This includes all properties that > simply access fields. But, in case of a form, you can't access f.e. the > controls of the form (or at least, you shouldn't count on). > If the form is destroyed in the sense, that it is collected, than there is > no reference to the instance left (if the GC worked right ;-) ), and so no > member of the instance can be accessed. > > Christof What confused me - and is clear now - is that Dispose(bool) will destroy the components / controls, but as someone else wrote if you have their important properties stored in simple instance variables then you can still access those until the form is destroyed (i.e. the garbage collector has kicked in and freed the object's memory). Cheers Ray |
|||||||||||||||||||||||