IntPtr を取るネイティブ関数を呼び出すときに、Sync ネイティブ関数を使用してそれを行う方法を理解しています。
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void Operation(SafeHandle handle)
{
var mustReleaseSafeHandle = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
handle.DangerousAddRef(ref mustReleaseSafeHandle);
if (mustReleaseSafeHandle) WinAPI.Operation(handle.DangerousGetHandle());
}
finally
{
if (mustReleaseSafeHandle) handle.DangerousRelease();
}
}
ネイティブ関数が非同期のときに DangerousRelease が確実に発生するようにするにはどうすればよいですか?
Hans Passant が提案するように、より多くのコンテキストを追加する私の非同期試行の疑似例を次に示します。
public static unsafe void Operation(SafeHandle fileHandle, SafeHandle nativeMemoryHandle, int offset)
{
var mustReleaseSafeHandle = false;
var ioCompletionCallback = new IOCompletionCallback((code, bytes, overlap) =>
{
if (mustReleaseSafeHandle) nativeMemoryHandle.DangerousRelease();
Overlapped.Free(overlap);
});
var overlapped = new Overlapped();
var nativeOverlapped = overlapped.Pack(ioCompletionCallback, null);
nativeMemoryHandle.DangerousAddRef(ref mustReleaseSafeHandle);
if (mustReleaseSafeHandle)
{
var memoryStartLocation = IntPtr.Add(nativeMemoryHandle.DangerousGetHandle(), offset);
if (!WinAPI.Operation(fileHandle, memoryStartLocation, offset, nativeOverlapped))
{
nativeMemoryHandle.DangerousRelease();
Overlapped.Free(nativeOverlapped);
}
}
else
{
Overlapped.Free(nativeOverlapped);
}
}