问题描述
我们在从.Net 4 C#应用程序保存文件时使用MoveFileTransactedW(也就是说,我们写入临时文件,然后将文件移动到其中实际位置)。
We are using MoveFileTransactedW when saving files from our .Net 4 C# application (that is, we write to a temporary file and then move the file to its actual location).
在两台独立的计算机(都是Windows 7)上,我们很少发生似乎对MoveFileTransactedW的调用永远不会返回的情况(至少根据我们查看的小型数据库) 。
On two separate computers (both Windows 7) we have had a rare occurrence where it seems the call to MoveFileTransactedW never returns (at least according to the minidumps we looked at).
执行移动的代码看起来像这样(我删除了一些代码来处理不支持事务的情况以及其他一些错误处理):
The code that executes the move, looks like this (i removed some code that handles the case where transactions arent supported as well as some other error handling):
var transaction = CreateTransaction( IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, IntPtr.Zero );
try {
bool result = MoveFileTransactedW( src, dest, IntPtr.Zero, IntPtr.Zero, MoveFileFlags.MOVEFILE_REPLACE_EXISTING | MoveFileFlags.MOVEFILE_WRITE_THROUGH, transaction );
result &= CommitTransaction( transaction );
if ( !result ) {
File.Replace( src, dest, null );
}
}
finally {
CloseHandle( transaction );
}
并且DLL导入:
[DllImport( "KtmW32.dll" )]
private static extern bool CommitTransaction( IntPtr transaction );
[DllImport( "Kernel32.dll" )]
private static extern bool CloseHandle( IntPtr handle );
[DllImport( "KtmW32.dll" )]
private static extern IntPtr CreateTransaction( IntPtr lpEventAttributes, IntPtr UOW, UInt32 createOptions, UInt32 isolationLevel, UInt32 isolationFlags, UInt32 timeOut, IntPtr description );
[return: MarshalAs( UnmanagedType.Bool )]
[DllImport( "kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true )]
private static extern bool MoveFileTransactedW( [In] string lpExistingFileName, [In] string lpNewFileName, [In] IntPtr lpProgressRoutine, [In] IntPtr lpData, [In] MoveFileFlags dwFlags, [In] IntPtr hTransaction );
任何想法可能导致什么?我尝试过各种场景,涉及在同一个文件上打开的其他事务,锁定文件等,但MoveFileTransactedW总是返回。
Any ideas what could cause this? I have tried various scenarios involving other transactions open on the same file, locking the files etc, but MoveFileTransactedW always returns.
stacktrace的最后一部分是:
The last part of the stacktrace is this:
> ()
> ntdll.dll!_KiFastSystemCallRet@0()
() + 0xc字节
ntdll.dll!_NtSetInformationFile@20() + 0xc bytes
() + 0x18c字节
kernel32.dll!_MoveFileWithProgressTransactedW@24() + 0x18c bytes
() + 0x47字节
kernel32.dll!_MoveFileTransactedW@24() + 0x47 bytes
[管理到原生过渡]
[Managed to Native Transition]
也许我应该避免使用MOVEFILE_WRITE_THROUGH标志?根据没有必要,但我发现描述有点不清楚,因此无论如何我添加了它:)
Perhaps i should avoid using the MOVEFILE_WRITE_THROUGH flag? According to http://msdn.microsoft.com/en-us/library/aa365241(v=vs.85).aspx it is not necessary, but i found the description a bit unclear, and therefore i added it anyway :)
推荐答案
我建议两件事:
- 删除MOVEFILE_WRITE_THROUGH标志(不确定这是否是问题)
- Remove the MOVEFILE_WRITE_THROUGH flag (not sure if this is the issue though)
- 调用CreateTransaction时,为第6个参数指定合理的超时,如果事务在程序中止,则实现一些重试逻辑
- When you call CreateTransaction, specify a reasonable timeout for the 6th parameter, and implement some retry logic if the transaction is aborted in your program
这篇关于是什么导致MoveFileTransactedW挂起?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!