我需要打开一个文件,但如果它当前不可用,我需要等到它准备好了.什么是最好的方法?
情景
我正在使用文件作为应用程序数据的持久缓存机制.这些数据需要经常读取和反序列化(只写一次,偶尔删除).我有一个清理过程,它运行在一个单独的线程上,确定不再需要哪些文件并删除它们.打开和读取文件可能同时发生(很少,但可能发生),我希望进程等待并尝试再次读取数据.
谢谢!
我不是try/catch IOException的忠实粉丝,因为:
您可以通过调用CreateFile并在/最终返回句柄时返回流来无异常地执行此操作:
public static System.IO.Stream WaitForExclusiveFileAccess(string filePath, int timeout)
{
IntPtr fHandle;
int errorCode;
DateTime start = DateTime.Now;
while(true)
{
fHandle = CreateFile(filePath, EFileAccess.GenericRead | EFileAccess.GenericWrite, EFileShare.None, IntPtr.Zero,
ECreationDisposition.OpenExisting, EFileAttributes.Normal, IntPtr.Zero);
if (fHandle != IntPtr.Zero && fHandle.ToInt64() != -1L)
return new System.IO.FileStream(fHandle, System.IO.FileAccess.ReadWrite, true);
errorCode = Marshal.GetLastWin32Error();
if (errorCode != ERROR_SHARING_VIOLATION)
break;
if (timeout >= 0 && (DateTime.Now - start).TotalMilliseconds > timeout)
break;
System.Threading.Thread.Sleep(100);
}
throw new System.IO.IOException(new System.ComponentModel.Win32Exception(errorCode).Message, errorCode);
}
#region Win32
const int ERROR_SHARING_VIOLATION = 32;
[Flags]
enum EFileAccess : uint
{
GenericRead = 0x80000000,
GenericWrite = 0x40000000
}
[Flags]
enum EFileShare : uint
{
None = 0x00000000,
}
enum ECreationDisposition : uint
{
OpenExisting = 3,
}
[Flags]
enum EFileAttributes : uint
{
Normal = 0x00000080,
}
[DllImport("kernel32.dll", EntryPoint = "CreateFileW", SetLastError = true, CharSet = CharSet.Unicode)]
static extern IntPtr CreateFile(
string lpFileName,
EFileAccess dwDesiredAccess,
EFileShare dwShareMode,
IntPtr lpSecurityAttributes,
ECreationDisposition dwCreationDisposition,
EFileAttributes dwFlagsAndAttributes,
IntPtr hTemplateFile);
#endregion
Run Code Online (Sandbox Code Playgroud)