2012-03-08 55 views
8

在Windows 7(或服務器)框上,UNC共享上有一個文件夾(跨機器UNC,而不是 localhost)。我們重命名該文件夾,然後檢查新文件夾位置是否存在文件。即使存在,File.Exists也需要將近5秒才能返回true。文件夾重命名後文件存在檢查返回UNC共享上的一個不正確的值

可以在https://github.com/davidebbo/NpmFolderRenameIssue上找到完整的repro。這裏是核心代碼:

// This file doesn't exist yet 
// Note that the presence of this existence check is what triggers the bug below!! 
Console.WriteLine("Exists (should be false): " + File.Exists("test/test2/myfile")); 

// Create a directory, with a file in it 
Directory.CreateDirectory("test/subdir/test"); 
File.WriteAllText("test/subdir/test/myfile", "Hello"); 

// Rename the directory 
Directory.Move("test/subdir/test", "test/test2"); 

var start = DateTime.UtcNow; 

// List the files at the new location. Here, our file shows up fine 
foreach (var path in Directory.GetFiles("test/test2")) 
{ 
    Console.WriteLine(path); 
} 

for (; ;) 
{ 
    // Now do a simple existence test. It should also be true, but when 
    // running on a (cross machine) UNC share, it takes almost 5 seconds to become true! 
    if (File.Exists("test/test2/myfile")) break; 

    Console.WriteLine("After {0} milliseconds, test/test2/myfile doesn't show as existing", 
     (DateTime.UtcNow - start).TotalMilliseconds); 
    Thread.Sleep(100); 
} 

Console.WriteLine("After {0} milliseconds, test/test2/myfile correctly shows as existing!", 
    (DateTime.UtcNow - start).TotalMilliseconds); 

所以它看起來像最初的生存確認導致緩存,造成這種虛假行爲存在的價值。

問題:這是什麼解釋?什麼是避免它的最好方法?

注意:在Windows上使用npm(節點包管理器)時,最初出現此問題。我在這裏的代碼是repro的C#端口。有關原始Node/npm問題,請參閱https://github.com/isaacs/npm/issues/2230。目標是找到解決問題的方法。

+1

請注意,調用'File.Exists'不會解決可能的競爭條件。我不確定這裏是否有必要。無論你在做什麼以響應'File.Exists',你都可以響應一個異常。 – 2012-03-08 08:05:19

+1

你可以看到這種行爲與各種網絡文件系統,雖然Win7是相當極端的價值緩存多久......用win2k8我看到這很少,而與Win7它是相當「正規」......我懷疑一些MS文件系統開發可以回答你的問題...得到一些幫助,因此你需要更清楚地描述你的目標IMO ... – Yahia 2012-03-08 08:07:16

+0

@Cody:請注意我在這裏關注你。如果Directory.GetFiles()列出它,File.Exists返回true似乎是合理的,否? – 2012-03-08 08:09:32

回答

10

David, 重定向器實現負面的「文件未找到」緩存,該緩存防止客戶端使用文件未找到的請求淹沒服務器。默認的緩存時間爲5秒,但可以通過修改註冊表FileNotFoundCacheLifetime值來控制緩存或通過將該值設置爲0。

詳細禁用它:http://technet.microsoft.com/en-us/library/ff686200(v=WS.10).aspx

+1

是的,就是這樣!將此FileNotFoundCacheLifetime值設置爲0將刪除該條件。當然,這可能會對系統產生負面影響,所以它可能不是一件聰明的事情。但我主要是在尋找解釋行爲的東西,而這確實如此。謝謝! – 2012-03-08 08:44:54

1

網絡代碼中存在多級緩存。這可能會減慢文件存在最終顯示的時間。

解決方案不會使用文件共享,而是創建一個簡單的客戶端/服務器體系結構,其中服務器從本地文件系統返回文件存在。這應該會加快物品檢測時間。

我的猜測是如果你試圖打開文件,即使File.Exists說它不存在,它應該正確打開,所以你可以使用服務器的存在信息。如果這不起作用,您可以簡單地將下載選項添加到服務器/客戶端體系結構中。

+1

事實上,該文件可以打開。查看其他答案;事實證明這是由文檔化的存在緩存功能引起的。 – 2012-03-08 08:46:33

1

一旦我知道了「找不到文件」緩存,我能夠通過使用FileInfo對象來解決問題,該對象實現了Refresh()方法。你的代碼可以做到這一點:

FileInfo testFile = new FileInfo("test/test2/myfile"); 
Console.WriteLine("Exists (should be false): " + testFile .Exists); 
Directory.Move("test/subdir/test", "test/test2"); 
testFile.Refresh(); 

// the FileInfo object should now be refreshed, and a second call to Exists will return a valid value 
if (testFile.Exists) 
{ 
    ... 
}