|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Garbage collection and callbacks from unmanaged code.I have a .NET application (VB) that passes the address of a delegate to unmanaged code in a DLL. The unmanaged code then uses the delegate as a call-back. This seems to work fine, but now I am worried about garbage collection. I am concerned that the location of the delegate might be altered as a result of other (unused) objects being garbage collected. This would probably cause undesirable results when the unmanaged DLL attempted to make a subsequent call-back operation. Although I haven't yet seen such a problem, I understand that garbage collection is largely uncontrollable and unpredictable. So I am worried about mysterious and sporadic problems appearing when the application is actually in use. To avoid this possibility, I tried "pinning" the delegate, but I get the error message: "Object contains non-primitive or non-blittable data." Are my concerns about this justified? If so, what (if anything) can I do to prevent this problem? For any who are interested, I have posted relevant code snippets below. Cheers, Randy Private Delegate Function mdgtDataInterface( _ ByVal strAction As String, _ ByVal intActionLen As Integer, _ <MarshalAs(UnmanagedType.SafeArray)> _ ByRef objaData() As Object) As aenmDataRequestStatus ... ... ' DataInterface is the .Net call-back routine. Dim dgtDataInterface As mdgtDataInterface = AddressOf DataInterface '''The following statement causes a System.ArgumentException. '''Dim gchDIPin As GCHandle = GCHandle.Alloc(dgtDataInterface, _ GCHandleType.Pinned) ... ' This calls the unmanaged code and passes the call-back delegate. Dim intStatus As Integer = RunUnmanaged(intModelAddress, _ dgtDataInterface, _ strMessage) ... ... ' This is the call-back routine Public Function DataInterface(ByVal strRequest As String, _ ByVal intRequestLength As Integer, _ <MarshalAs(UnmanagedType.SafeArray)> _ ByRef objaData() As Object) _ As aenmDataRequestStatus ... ... >Are my concerns about this justified? If so, what (if anything) can I As long as you make sure the delegate itself doesn't get garbage>do to prevent this problem? collected, you have nothing to worry about. Mattias -- Mattias Sjögren [C# MVP] mattias @ mvps.org http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com Please reply only to the newsgroup. Hello, Mattias,
Thanks for the reassurance. A reference to the delegate is maintained for the duration of the time that the unmanaged code is active, so there is no worry about the delegate itself being garbage collected. What worries me though, is the following quote from: http://msdn2.microsoft.com/en-us/library/f144e03t.aspx <quote> During a collection, the garbage collector examines the managed heap, looking for the blocks of address space occupied by unreachable objects. As it discovers each unreachable object, it uses a memory-copying function to compact the reachable objects in memory, freeing up the blocks of address spaces allocated to unreachable objects. Once the memory for the reachable objects has been compacted, the garbage collector makes the necessary pointer corrections so that the application's roots point to the objects in their new locations. <end-quote> This sounds to me like the memory location of the delegate is subject to change. The unmanaged code (Fortran in this case) stores the address of the delegate in an unmanaged integer variable that is not subject to adjustment by the garbage collector. So I have trouble understanding why I shouldn't worry. ;-) I guess in addition to reassurance, I am also seeking enlightenment. I can imagine a scheme whereby delegates are treated specially and never moved as a result of garbage collection. Or I can imagine an indirection scheme where delegates are always referenced through a fixed pointer, and it is the address of this pointer that is passed to the unmanaged code. Incidentally, I seem to have omitted the declaration of "RunUnmanaged" in my previous post. It it: Public Function RunUnmanaged(ByVal intFunctionPointer As Integer, _ ByVal dgtCallBackAddr As System.Delegate, _ <MarshalAs(UnmanagedType.BStr)> ByRef strMessage As String) _ As Integer But these imagined schemes are just idle speculation on my part. The best reassurance would come from my understanding of how this actually operates. But, so far, I haven't been able to find any documentation that makes this clear to me. Can you point me towards the light? Cheers, Randy Mattias Sjögren wrote: Show quoteHide quote >>Are my concerns about this justified? If so, what (if anything) can I >>do to prevent this problem? > > > As long as you make sure the delegate itself doesn't get garbage > collected, you have nothing to worry about. > > > Mattias > >This sounds to me like the memory location of the delegate is subject to Just as you guessed yourself, the native code doesn't get a direct>change. The unmanaged code (Fortran in this case) stores the address of >the delegate in an unmanaged integer variable that is not subject to >adjustment by the garbage collector. > >So I have trouble understanding why I shouldn't worry. ;-) pointer to the delegate but rather to some thunk code generated by the marshaler. This indirection ensures that the native function pointer remains valid even if the delegate is being moved. Mattias -- Mattias Sjögren [C# MVP] mattias @ mvps.org http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com Please reply only to the newsgroup. Hello, Mattias,
Many thanks for that. My reassurance is now complete. Do you know of a good reference where this whole area of "marshaling" (and particularly interacting with unmanaged code) is documented in a tutorial fashion. I have read the MS reference docs about this, but I seem to be missing some of the basics and language required to understand them. :-( I have one other concern related to SafeArray interactions between managed and unmanaged code that I will post as a new thread, but I wouldn't mind being able to learn a little more about the whole area. Again, thanks for your reply. Cheers, Randy Mattias Sjögren wrote: Show quoteHide quote >>This sounds to me like the memory location of the delegate is subject to >>change. The unmanaged code (Fortran in this case) stores the address of >>the delegate in an unmanaged integer variable that is not subject to >>adjustment by the garbage collector. >> >>So I have trouble understanding why I shouldn't worry. ;-) > > > Just as you guessed yourself, the native code doesn't get a direct > pointer to the delegate but rather to some thunk code generated by the > marshaler. This indirection ensures that the native function pointer > remains valid even if the delegate is being moved. > > > Mattias >
Adding button programatically - NON-FUNCTIONAL!!
Checking for new versions in a setup project ADO With SQL Transactions Preventing Explorer Window from Displaying when Pen Drive Inserted Error on Graphics CompositingMode.SourceCopy Numeric Variables converting from combobox.text to long() sending email when running on diff machine Can anyone convert this to VB? Getting Extended File Properties |
|||||||||||||||||||||||