Nếu bạn đang cố gắng xóa đệ quy thư mục a
và thư mục a\b
đang mở trong Explorer, b
sẽ bị xóa nhưng bạn sẽ nhận được lỗi 'thư mục không trống' a
ngay cả khi nó trống khi bạn đi và nhìn. Thư mục hiện tại của bất kỳ ứng dụng nào (bao gồm cả Explorer) vẫn giữ một tay cầm cho thư mục . Khi bạn gọi Directory.Delete(true)
, nó sẽ xóa từ dưới lên : b
, sau đó a
. Nếu b
được mở trong Explorer, Explorer sẽ phát hiện việc xóa b
, thay đổi thư mục lên trên cd ..
và dọn sạch các thẻ điều khiển mở. Do hệ thống tệp hoạt động không đồng bộ, nên Directory.Delete
hoạt động không thành công do xung đột với Explorer.
Giải pháp chưa hoàn chỉnh
Ban đầu tôi đã đăng giải pháp sau đây, với ý tưởng làm gián đoạn luồng hiện tại để cho phép Explorer có thời gian giải phóng tay cầm thư mục.
// incomplete!
try
{
Directory.Delete(path, true);
}
catch (IOException)
{
Thread.Sleep(0);
Directory.Delete(path, true);
}
Nhưng điều này chỉ hoạt động nếu thư mục mở là con ngay lập tức của thư mục bạn đang xóa. Nếu a\b\c\d
được mở trong Explorer và bạn sử dụng tính năng này a
, kỹ thuật này sẽ thất bại sau khi xóa d
và c
.
Một giải pháp tốt hơn
Phương pháp này sẽ xử lý xóa cấu trúc thư mục sâu ngay cả khi một trong các thư mục cấp thấp hơn được mở trong Explorer.
/// <summary>
/// Depth-first recursive delete, with handling for descendant
/// directories open in Windows Explorer.
/// </summary>
public static void DeleteDirectory(string path)
{
foreach (string directory in Directory.GetDirectories(path))
{
DeleteDirectory(directory);
}
try
{
Directory.Delete(path, true);
}
catch (IOException)
{
Directory.Delete(path, true);
}
catch (UnauthorizedAccessException)
{
Directory.Delete(path, true);
}
}
Mặc dù có thêm công việc đệ quy, chúng tôi vẫn phải xử lý những UnauthorizedAccessException
gì có thể xảy ra trên đường đi. Không rõ liệu lần thử xóa đầu tiên có mở đường cho lần thứ hai, lần thành công hay không, nếu đó chỉ là sự chậm trễ về thời gian được đưa ra bởi việc ném / bắt một ngoại lệ cho phép hệ thống tệp bắt kịp.
Bạn có thể giảm số lượng các trường hợp ngoại lệ được ném và bắt trong các điều kiện điển hình bằng cách thêm một Thread.Sleep(0)
ở đầu try
khối. Ngoài ra, có một rủi ro là dưới tải hệ thống nặng, bạn có thể bay qua cả hai Directory.Delete
lần thử và thất bại. Xem xét giải pháp này là điểm khởi đầu để xóa đệ quy mạnh mẽ hơn.
Câu trả lời chung
Giải pháp này chỉ giải quyết các đặc thù của việc tương tác với Windows Explorer. Nếu bạn muốn thao tác xóa khối cứng, một điều cần lưu ý là mọi thứ (trình quét vi-rút, bất cứ thứ gì) đều có thể xử lý mở đối với những gì bạn đang cố xóa bất cứ lúc nào. Vì vậy, bạn phải thử lại sau. Bao nhiêu lần sau và bao nhiêu lần bạn thử, tùy thuộc vào mức độ quan trọng của đối tượng bị xóa. Như MSDN chỉ ra ,
Mã lặp tập tin mạnh mẽ phải tính đến nhiều phức tạp của hệ thống tập tin.
Tuyên bố vô tội này, chỉ được cung cấp với một liên kết đến tài liệu tham khảo NTFS, nên làm cho tóc của bạn đứng lên.
( Chỉnh sửa : Rất nhiều. Câu trả lời này ban đầu chỉ có giải pháp đầu tiên, không đầy đủ.)