นี่เป็นวิธีแก้ปัญหาที่รวดเร็วเป็นพิเศษซึ่งในที่สุดฉันก็นำไปใช้ นี่ฉันใช้ WinAPI และฟังก์ชั่FindFirstFile , FindNextFile จะช่วยให้หลีกเลี่ยงการแจงนับของรายการทั้งหมดในโฟลเดอร์และหยุดทันทีหลังจากการตรวจสอบวัตถุแรกในโฟลเดอร์ วิธีนี้เร็วกว่า ~ 6 (!!) มากกว่าที่อธิบายไว้ข้างต้น 250 สายใน 36 มิลลิวินาที!
private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct WIN32_FIND_DATA
{
public uint dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32.dll")]
private static extern bool FindClose(IntPtr hFindFile);
public static bool CheckDirectoryEmpty_Fast(string path)
{
if (string.IsNullOrEmpty(path))
{
throw new ArgumentNullException(path);
}
if (Directory.Exists(path))
{
if (path.EndsWith(Path.DirectorySeparatorChar.ToString()))
path += "*";
else
path += Path.DirectorySeparatorChar + "*";
WIN32_FIND_DATA findData;
var findHandle = FindFirstFile(path, out findData);
if (findHandle != INVALID_HANDLE_VALUE)
{
try
{
bool empty = true;
do
{
if (findData.cFileName != "." && findData.cFileName != "..")
empty = false;
} while (empty && FindNextFile(findHandle, out findData));
return empty;
}
finally
{
FindClose(findHandle);
}
}
throw new Exception("Failed to get directory first file",
Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()));
}
throw new DirectoryNotFoundException();
}
ฉันหวังว่ามันจะเป็นประโยชน์สำหรับใครบางคนในอนาคต