Re: Use of GCHandle.Alloc and Free
Or perhaps use GC.KeepAlive On Mon, Nov 1, 2010 at 9:34 AM, David Kean wrote: > If by using a local variable you mean local field, then yes this is > reliable. > > > > *From:* ozdotnet-boun...@ozdotnet.com [mailto: > ozdotnet-boun...@ozdotnet.com] *On Behalf Of *Greg Keogh > *Sent:* Sunday, October 31, 2010 1:44 PM > *To:* 'ozDotNet' > *Subject:* FW: Use of GCHandle.Alloc and Free > > > > You may recall two weeks ago I had to use code like this to stop a COM > object from being collected: > > > > GCHandle cursorHandle = GCHandle.Alloc(feature.Cursor, > GCHandleType.Normal); > > > > A few people suggested that it was overkill and simply making a local > variable reference to feature.Cursor would fix the problem. > > > > It does! > > > > Although I wonder if using a dummy reference is reliable. In Debug mode it > works, but in Release mode might it get optimised away and my problem will > return? I didn’t try it. > > > > Greg >
RE: Use of GCHandle.Alloc and Free
If by using a local variable you mean local field, then yes this is reliable. From: ozdotnet-boun...@ozdotnet.com [mailto:ozdotnet-boun...@ozdotnet.com] On Behalf Of Greg Keogh Sent: Sunday, October 31, 2010 1:44 PM To: 'ozDotNet' Subject: FW: Use of GCHandle.Alloc and Free You may recall two weeks ago I had to use code like this to stop a COM object from being collected: GCHandle cursorHandle = GCHandle.Alloc(feature.Cursor, GCHandleType.Normal); A few people suggested that it was overkill and simply making a local variable reference to feature.Cursor would fix the problem. It does! Although I wonder if using a dummy reference is reliable. In Debug mode it works, but in Release mode might it get optimised away and my problem will return? I didn't try it. Greg
FW: Use of GCHandle.Alloc and Free
You may recall two weeks ago I had to use code like this to stop a COM object from being collected: GCHandle cursorHandle = GCHandle.Alloc(feature.Cursor, GCHandleType.Normal); A few people suggested that it was overkill and simply making a local variable reference to feature.Cursor would fix the problem. It does! Although I wonder if using a dummy reference is reliable. In Debug mode it works, but in Release mode might it get optimised away and my problem will return? I didn't try it. Greg
RE: Use of GCHandle.Alloc and Free
>I might be off track, but don't you need to call >`Marshall.ReleaseComObject(object)` on all managed references to COM The VB6 programmers wants the 'feature' objects (there a multiple ones) and the 'Cursor' inside each one to live for the lifetime of the App. I didn't mention it, but there is a kind of factory class that makes the COM objects for me and it knows when to ReleaseComObject on them all at shutdown time. So I *hope* their lifetimes are managed correctly, but with COM there is so much magic stuff happening I can't shake off this fear that something rotten is happening that I can't see. It seems to be working correctly anyway, which is a good sign I guess! Mark, David, I'll try the change you suggested with a simple reference and let you know what happens. I didn't think of doing that because I already had an event listener on the object and I thought that would be enough to keep it alive. Greg
RE: Use of GCHandle.Alloc and Free
I might be off track, but don't you need to call `Marshall.ReleaseComObject(object)` on all managed references to COM objects? My experience a few years back was that when you allocated and released COM objects many times you run out of some sort of handle that then causes things to randomly screw up. But by calling `ReleaseComObject` everything went fine. -Original Message- From: ozdotnet-boun...@ozdotnet.com [mailto:ozdotnet-boun...@ozdotnet.com] On Behalf Of David Kean Sent: Wednesday, 13 October 2010 01:41 To: ozDotNet Subject: RE: Use of GCHandle.Alloc and Free Yes, you don't need a GCHandle here - as Mark mentioned simply store away the reference of the COM objects in a field until they are no longer needed. -Original Message- From: ozdotnet-boun...@ozdotnet.com [mailto:ozdotnet-boun...@ozdotnet.com] On Behalf Of Mark Hurd Sent: Tuesday, October 12, 2010 6:32 AM To: ozDotNet Subject: Re: Use of GCHandle.Alloc and Free On Tue, Oct 12, 2010 at 6:29 PM, Greg Keogh wrote: > Folks, we had a shocking problem today where C# code was listening for > events from a VB6 component. The COM classes exposed by the VB6 app > are nested and a bit complicated to describe, but a nested class which > exposed events was randomly producing the dreaded "COM object that has > been separated from its underlying RCW cannot be used". The random > nature of the problem hinted that it was garbage or dispose related. > After a bit of suffering I found the following solution (feature and > Cursor are COM > classes): > > GCHandle cursorHandle = GCHandle.Alloc(feature.Cursor, > GCHandleType.Normal); > > feature.Cursor.NotifyMoveNext += event handler; > > feature.ShowModalDialog(...); > > if (cursorHandle.IsAllocated) > > { > > cursorHandle.Free(); > > feature.Cursor.NotifyMoveNext -= event handler; > > } > > It used to randomly die on the removal of the event handler. The Alloc > and Free seem to have totally solved the problem. > > This code seems a bit obscure and arcane, so I was wondering if anyone > had comments on it. Perhaps there are better ways. > > Greg It looks to me simply like you need to hold the reference to feature.Cursor until you remove the event handler. To test this, simply change your code to var cursorHolder = feature.Cursor; feature.Cursor.NotifyMoveNext += event handler; feature.ShowModalDialog(...); feature.Cursor.NotifyMoveNext -= event handler; GC.KeepAlive(cursorHolder); Of course if other things are afoot and sometimes cursorHandle.IsAllocated is False, then the above may not be what you need. -- Regards, Mark Hurd, B.Sc.(Ma.)(Hons.)
RE: Use of GCHandle.Alloc and Free
Yes, you don't need a GCHandle here - as Mark mentioned simply store away the reference of the COM objects in a field until they are no longer needed. -Original Message- From: ozdotnet-boun...@ozdotnet.com [mailto:ozdotnet-boun...@ozdotnet.com] On Behalf Of Mark Hurd Sent: Tuesday, October 12, 2010 6:32 AM To: ozDotNet Subject: Re: Use of GCHandle.Alloc and Free On Tue, Oct 12, 2010 at 6:29 PM, Greg Keogh wrote: > Folks, we had a shocking problem today where C# code was listening for > events from a VB6 component. The COM classes exposed by the VB6 app > are nested and a bit complicated to describe, but a nested class which > exposed events was randomly producing the dreaded "COM object that has > been separated from its underlying RCW cannot be used". The random > nature of the problem hinted that it was garbage or dispose related. > After a bit of suffering I found the following solution (feature and > Cursor are COM > classes): > > GCHandle cursorHandle = GCHandle.Alloc(feature.Cursor, > GCHandleType.Normal); > > feature.Cursor.NotifyMoveNext += event handler; > > feature.ShowModalDialog(...); > > if (cursorHandle.IsAllocated) > > { > > cursorHandle.Free(); > > feature.Cursor.NotifyMoveNext -= event handler; > > } > > It used to randomly die on the removal of the event handler. The Alloc > and Free seem to have totally solved the problem. > > This code seems a bit obscure and arcane, so I was wondering if anyone > had comments on it. Perhaps there are better ways. > > Greg It looks to me simply like you need to hold the reference to feature.Cursor until you remove the event handler. To test this, simply change your code to var cursorHolder = feature.Cursor; feature.Cursor.NotifyMoveNext += event handler; feature.ShowModalDialog(...); feature.Cursor.NotifyMoveNext -= event handler; GC.KeepAlive(cursorHolder); Of course if other things are afoot and sometimes cursorHandle.IsAllocated is False, then the above may not be what you need. -- Regards, Mark Hurd, B.Sc.(Ma.)(Hons.)
Re: Use of GCHandle.Alloc and Free
On Tue, Oct 12, 2010 at 6:29 PM, Greg Keogh wrote: > Folks, we had a shocking problem today where C# code was listening for > events from a VB6 component. The COM classes exposed by the VB6 app are > nested and a bit complicated to describe, but a nested class which exposed > events was randomly producing the dreaded “COM object that has been > separated from its underlying RCW cannot be used”. The random nature of the > problem hinted that it was garbage or dispose related. After a bit of > suffering I found the following solution (feature and Cursor are COM > classes): > > GCHandle cursorHandle = GCHandle.Alloc(feature.Cursor, GCHandleType.Normal); > > feature.Cursor.NotifyMoveNext += event handler; > > feature.ShowModalDialog(...); > > if (cursorHandle.IsAllocated) > > { > > cursorHandle.Free(); > > feature.Cursor.NotifyMoveNext -= event handler; > > } > > It used to randomly die on the removal of the event handler. The Alloc and > Free seem to have totally solved the problem. > > This code seems a bit obscure and arcane, so I was wondering if anyone had > comments on it. Perhaps there are better ways. > > Greg It looks to me simply like you need to hold the reference to feature.Cursor until you remove the event handler. To test this, simply change your code to var cursorHolder = feature.Cursor; feature.Cursor.NotifyMoveNext += event handler; feature.ShowModalDialog(...); feature.Cursor.NotifyMoveNext -= event handler; GC.KeepAlive(cursorHolder); Of course if other things are afoot and sometimes cursorHandle.IsAllocated is False, then the above may not be what you need. -- Regards, Mark Hurd, B.Sc.(Ma.)(Hons.)
Use of GCHandle.Alloc and Free
Folks, we had a shocking problem today where C# code was listening for events from a VB6 component. The COM classes exposed by the VB6 app are nested and a bit complicated to describe, but a nested class which exposed events was randomly producing the dreaded "COM object that has been separated from its underlying RCW cannot be used". The random nature of the problem hinted that it was garbage or dispose related. After a bit of suffering I found the following solution (feature and Cursor are COM classes): GCHandle cursorHandle = GCHandle.Alloc(feature.Cursor, GCHandleType.Normal); feature.Cursor.NotifyMoveNext += event handler; feature.ShowModalDialog(...); if (cursorHandle.IsAllocated) { cursorHandle.Free(); feature.Cursor.NotifyMoveNext -= event handler; } It used to randomly die on the removal of the event handler. The Alloc and Free seem to have totally solved the problem. This code seems a bit obscure and arcane, so I was wondering if anyone had comments on it. Perhaps there are better ways. Greg