最近使用するように変更した次のコードを検討してくださいFileStream.SafeFileHandle
。
public static void FastWrite<T>(FileStream fs, T[] array, int offset, int count) where T: struct
{
int sizeOfT = Marshal.SizeOf(typeof(T));
GCHandle gcHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
try
{
uint bytesWritten;
uint bytesToWrite = (uint)(count * sizeOfT);
var overlapped = new NativeOverlapped();
if
(
!WriteFile
(
fs.SafeFileHandle,
new IntPtr(gcHandle.AddrOfPinnedObject().ToInt64() + (offset*sizeOfT)),
bytesToWrite,
out bytesWritten,
ref overlapped
)
)
{
throw new IOException("Unable to write file.", new Win32Exception(Marshal.GetLastWin32Error()));
}
Debug.Assert(bytesWritten == bytesToWrite);
GC.KeepAlive(fs); // <--- Is this really not necessary?
}
finally
{
gcHandle.Free();
}
}
[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool WriteFile
(
SafeFileHandle hFile,
IntPtr lpBuffer,
uint nNumberOfBytesToWrite,
out uint lpNumberOfBytesWritten,
ref NativeOverlapped lpOverlapped
);
Windows API呼び出しが返さGC.KeepAlive(fs)
れるまで FileStream がガベージ コレクションされないようにするために、以前に を追加していました。WriteFile()
ただし、SafeFileHandle
コード分析を使用するように変更した後、次の場合は不要であることがわかりましたwarning CA2004: Remove calls to GC.KeepAlive
。
SafeHandle の使用法に変換する場合は、GC.KeepAlive (オブジェクト) へのすべての呼び出しを削除します。
のドキュメントを参照しましたFileStream.SafeFileHandle
が、 への呼び出しを削除しても本当に安全かどうかは不明ですGC.KeepAlive()
。
削除しても安全ですか?そして、私はそれを正しく使用していますか?
また、SafeHandle の使用に関する適切なドキュメントを教えてくれる人はいますか?