1

When you are passing an unmanaged handle (stored in either IntPtr or SafeHandle at the managed side) from managed to unmanaged code to do overlapped I/O, what is the correct approach?

  • use a SafeHandle to wrap the (IntPtr) OS handle in,
  • or use GCHandle.Alloc(IntPtrHandle, GCHandleType.Pinned) to pin it?

I am currently using a SafeHandle in combination with a NativeOverlapped structure, but I'm beginning to suspect more and more that GC is moving either or both around in memory while unmanaged overlapped IO is in progress.

Would I better go back to using an IntPtr instead of a SafeHandle, and use a GCHandle structure to pin it?

Or is the right way a combination of all, i.e. in your NativeOverlapped, use a pinned version of the IntPtr which is in its turn coming from the SafeHandle?

-- EDIT

Reflecting about this during lunch, I got the idea that I'm being stupid. It must be the overlapped structure that needs to be pinned, not the handle in it. Is that the right (best) answer?

Luc VdV
  • 1,088
  • 9
  • 14
  • The buffer needs to be pinned, not the handle. Using a SafeHandle to take advantage of the critical finalizer is a no-brainer. You should not be doing this at all, all conceivable OS handles types already have a .NET wrapper that supports asynchronous I/O. And do it a lot [more efficient](http://stackoverflow.com/a/7555664/17034) than you could possibly do it. But if you don't tell us what kind of handle this is then you, and above all other programmers, can't get the best answer. Stop treating SO as your personal helpdesk please. – Hans Passant Mar 10 '17 at 11:52
  • 1
    The buffer in this case is unmanaged. So is the actual handle itself. The only thing managed is the NativeOverlapped structure that is passed to ReadFile and WriteFile calls. – Luc VdV Mar 10 '17 at 12:49
  • 1
    Sorry, half of my comment dropped off. You are absolutely right about all kinds of things having .Net wrappers, and I would love to be able to use the newer stuff. But that goes only if you assume that only new code is ever written, and nobody has to maintain and extend 15 year old projects. And that is not uncommon, as it seems (from a Slashdot thread) that even some COBOL code is still being maintained ;) -- And finally, do you think many questions appear on SO that are NOT someone with a problem trying to get help as if it were a personal helpdesk? – Luc VdV Mar 10 '17 at 13:02
  • Not posting this as an answer, although I think it is a large part of it: the Overlapped (or NativeOverlapped) structure must be pinned. After all, you are passing it to a win32api function that will use it only some time later, at completion of an I/O operation, meaning that the GC can interfere in the mean time if you don't pin it. Pinning forbids the GC from moving it in memory (see 'pinned' at https://msdn.microsoft.com/en-us/library/83y4ak54(v=vs.110).aspx). – Luc VdV Mar 10 '17 at 14:00

0 Answers0