Weird, unexplained occurance...
-
I've been working on a CRS system, and was running into a nasty error... For some reason every ~16 or so search queries, the program would crash, and give me a WIN32 exception, telling me that my program had used up all its allocated handles. Ok, so I wasn't disposing of my objects correctly somewhere... After much searching, I found that the foreach loop that was disposing of the results was not working as expected. (the search results were displayed using Panels). If I called:
int i = window.FlowPanel.Controls.Count;
It would return the expected number of (say) 20. However when I ran:foreach (Control c in window.FlowPanel.Controls) { c.Dispose(); }
It would cut out of the foreach loop at the 10th object. If I ran the same foreach loop directly afterwards, it would cut out at the 5th object etc etc. I solved the problem by using this snippet:while (window.FlowPanel.Controls.Count > 0) { foreach (Control c in window.FlowPanel.Controls) { c.Dispose(); } } GC.Collect();
This solved the problem, but can anyone explain this behaviour? Cheers, Mark.Mark Brock "We're definitely not going to make a G or a PG version of this. It's not PillowfightCraft." -- Chris Metzen
-
I've been working on a CRS system, and was running into a nasty error... For some reason every ~16 or so search queries, the program would crash, and give me a WIN32 exception, telling me that my program had used up all its allocated handles. Ok, so I wasn't disposing of my objects correctly somewhere... After much searching, I found that the foreach loop that was disposing of the results was not working as expected. (the search results were displayed using Panels). If I called:
int i = window.FlowPanel.Controls.Count;
It would return the expected number of (say) 20. However when I ran:foreach (Control c in window.FlowPanel.Controls) { c.Dispose(); }
It would cut out of the foreach loop at the 10th object. If I ran the same foreach loop directly afterwards, it would cut out at the 5th object etc etc. I solved the problem by using this snippet:while (window.FlowPanel.Controls.Count > 0) { foreach (Control c in window.FlowPanel.Controls) { c.Dispose(); } } GC.Collect();
This solved the problem, but can anyone explain this behaviour? Cheers, Mark.Mark Brock "We're definitely not going to make a G or a PG version of this. It's not PillowfightCraft." -- Chris Metzen
It's not that unexplained - Think of it this way: If you have a list and you iterate through it, what happens when you delete one of the list entries? What is the next entry for an entry which has been deleted? What happens when the Controls list is traversed by a different process? Since foreach does effectively that - calls Controls.Next each time round the loop - it is very understandable that at some point you will have a problem. Normally, you would get a "Collection was modified; enumeration operation may not execute" exception, but I guess Dispose doesn't check that! Use Controls.Remove to take the controls out of the list, then Dispose them. You will need to need to modify the foreach to a for loop (and I suggest iterating backwards from the last to the first, to make it safer.) You will probably find you can rely on the frame work to do the dispose this way.
No trees were harmed in the sending of this message; however, a significant number of electrons were slightly inconvenienced. This message is made of fully recyclable Zeros and Ones
-
I've been working on a CRS system, and was running into a nasty error... For some reason every ~16 or so search queries, the program would crash, and give me a WIN32 exception, telling me that my program had used up all its allocated handles. Ok, so I wasn't disposing of my objects correctly somewhere... After much searching, I found that the foreach loop that was disposing of the results was not working as expected. (the search results were displayed using Panels). If I called:
int i = window.FlowPanel.Controls.Count;
It would return the expected number of (say) 20. However when I ran:foreach (Control c in window.FlowPanel.Controls) { c.Dispose(); }
It would cut out of the foreach loop at the 10th object. If I ran the same foreach loop directly afterwards, it would cut out at the 5th object etc etc. I solved the problem by using this snippet:while (window.FlowPanel.Controls.Count > 0) { foreach (Control c in window.FlowPanel.Controls) { c.Dispose(); } } GC.Collect();
This solved the problem, but can anyone explain this behaviour? Cheers, Mark.Mark Brock "We're definitely not going to make a G or a PG version of this. It's not PillowfightCraft." -- Chris Metzen
You're changing the collection you're iterating through-- So the object you started off with at the beginning of the loop is not the same one at the end. I'm surprised it even let you do that... a
for(int x=FlowPanel.Controls.Count-1; x>=0; x--)
{
FlowPanel.Controls(x).Dispose();
}should do the trick, I think.
var question = (_2b || !(_2b));
-
It's not that unexplained - Think of it this way: If you have a list and you iterate through it, what happens when you delete one of the list entries? What is the next entry for an entry which has been deleted? What happens when the Controls list is traversed by a different process? Since foreach does effectively that - calls Controls.Next each time round the loop - it is very understandable that at some point you will have a problem. Normally, you would get a "Collection was modified; enumeration operation may not execute" exception, but I guess Dispose doesn't check that! Use Controls.Remove to take the controls out of the list, then Dispose them. You will need to need to modify the foreach to a for loop (and I suggest iterating backwards from the last to the first, to make it safer.) You will probably find you can rely on the frame work to do the dispose this way.
No trees were harmed in the sending of this message; however, a significant number of electrons were slightly inconvenienced. This message is made of fully recyclable Zeros and Ones
Damnit, beat me to the punch. ;)
var question = (_2b || !(_2b));
-
You're changing the collection you're iterating through-- So the object you started off with at the beginning of the loop is not the same one at the end. I'm surprised it even let you do that... a
for(int x=FlowPanel.Controls.Count-1; x>=0; x--)
{
FlowPanel.Controls(x).Dispose();
}should do the trick, I think.
var question = (_2b || !(_2b));
Sorry about beating you to it - it was just luck - but I still think using Remove from the controls list will be a better solution than Dispose!
No trees were harmed in the sending of this message; however, a significant number of electrons were slightly inconvenienced. This message is made of fully recyclable Zeros and Ones
-
Sorry about beating you to it - it was just luck - but I still think using Remove from the controls list will be a better solution than Dispose!
No trees were harmed in the sending of this message; however, a significant number of electrons were slightly inconvenienced. This message is made of fully recyclable Zeros and Ones
OriginalGriff wrote:
Remove from the controls list will be a better solution than Dispose!
Agreed, no arguments there. Didn't think it through completely ;>
var question = (_2b || !(_2b));
-
It's not that unexplained - Think of it this way: If you have a list and you iterate through it, what happens when you delete one of the list entries? What is the next entry for an entry which has been deleted? What happens when the Controls list is traversed by a different process? Since foreach does effectively that - calls Controls.Next each time round the loop - it is very understandable that at some point you will have a problem. Normally, you would get a "Collection was modified; enumeration operation may not execute" exception, but I guess Dispose doesn't check that! Use Controls.Remove to take the controls out of the list, then Dispose them. You will need to need to modify the foreach to a for loop (and I suggest iterating backwards from the last to the first, to make it safer.) You will probably find you can rely on the frame work to do the dispose this way.
No trees were harmed in the sending of this message; however, a significant number of electrons were slightly inconvenienced. This message is made of fully recyclable Zeros and Ones
-
You're changing the collection you're iterating through-- So the object you started off with at the beginning of the loop is not the same one at the end. I'm surprised it even let you do that... a
for(int x=FlowPanel.Controls.Count-1; x>=0; x--)
{
FlowPanel.Controls(x).Dispose();
}should do the trick, I think.
var question = (_2b || !(_2b));