等待文件锁被释放的正确模式是什么?

Mic*_*cah 6 .net c# locking

我需要打开一个文件,但如果它当前不可用,我需要等到它准备好了.什么是最好的方法?

情景

我正在使用文件作为应用程序数据的持久缓存机制.这些数据需要经常读取和反序列化(只写一次,偶尔删除).我有一个清理过程,它运行在一个单独的线程上,确定不再需要哪些文件并删除它们.打开和读取文件可能同时发生(很少,但可能发生),我希望进程等待并尝试再次读取数据.

谢谢!

csh*_*net 9

我不是try/catch IOException的忠实粉丝,因为:

  1. 异常的原因未知.
  2. 我不喜欢"预期的"异常,因为我经常在异常时运行.

您可以通过调用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)


Ter*_*ver 0

像所有“最好的方法是什么”问题一样,这个问题取决于您的需求。一些很容易想到的选项:

  1. 中止尝试
  2. 循环直到文件解锁
  3. 询问用户该怎么办

你选择哪一个取决于你如何处理它。