我目前面臨一個由多個組件組成的應用程式的問題。應用程式的一個組件會定期檢查網路驅動器上的新檔案并將它們復制到本地檔案夾中。應用程式的另一個組件使用FileSystemWatcher來監視本地檔案夾中的任何新檔案。如果復制了新檔案,則呼叫Created事件,FileSystemWatcher然后應用程式將讀取檔案內容并將檔案匯入資料庫。為了防止應用程式在檔案完全復制到本地檔案夾之前嘗試讀取檔案,它會定期呼叫以下函式,直到它回傳false:
private bool isFileLocked(string filePath)
{
try
{
if (!File.Exists(filePath))
{
return false;
}
using (FileStream fs = File.OpenRead(filePath))
{
}
return false;
}
catch (IOException)
{
return true;
}
}
不幸的是,這似乎并不適用于所有情況。有時,我注意到檔案在完全寫入本地檔案夾之前已被讀取。發生這種情況時,嘗試復制檔案的組件會收到以下錯誤:
System.IO.IOException: The process cannot access the file '...' because it is being used by another process.
復制檔案的組件是用 PowerShell 撰寫的,并使用以下 Cmdlet 進行復制:
Copy-Item $currentfile.FullName -Destination "$destfolder" –Force -ErrorAction Stop
使用FileSystemWatcher并匯入檔案的組件是基于 C# 的 Windows 服務。如何在檔案完全復制到本地檔案夾之前阻止它讀取檔案?
uj5u.com熱心網友回復:
如果您不擔心一點延遲- 它可能會解決您的問題:
static void Main(string[] args)
{
FileSystemWatcher fsw = new FileSystemWatcher("SomePathToFolder");
fsw.EnableRaisingEvents = true;
fsw.Created = async (s, a) =>
{
while (FileIsLocked(a.FullPath))
{
Console.WriteLine($"File {a.Name} is locked!");
await Task.Delay(TimeSpan.FromSeconds(5)); // 5 seconds delay between checks
}
Console.WriteLine($"File {a.Name} available!");
// You can put here another delay to be 102% sure that file is free,
// but I suppose this is too much.
using (FileStream fs = File.OpenRead(a.FullPath))
{
Console.WriteLine($"File {a.Name} opened for reading.");
// Do what you need
await Task.Run(() => ImportFileToDatabase(fs));
}
Console.WriteLine($"File {a.Name} closed.");
};
Console.ReadKey();
}
static bool FileIsLocked(string filePath)
{
if (!File.Exists(filePath))
return false;
try
{
using (FileStream fs = File.OpenRead(filePath)) { }
return false;
}
catch { }
return true;
}
uj5u.com熱心網友回復:
這里建議了一些解決方案。我在使用時遇到了類似的問題FileSystemWatcher。這是我使用的(簡化):
async Task<FileStream> OpenWaitAsync(string path, TimeSpan interval, CancellationToken cancellationToken = default)
{
const int ERROR_SHARING_VIOLATION = unchecked((int)0x80070020);
while (true)
{
try
{
return File.OpenRead(path);
}
catch (IOException ioe) when (ioe.HResult == ERROR_SHARING_VIOLATION)
{
await Task.Delay(interval, cancellationToken);
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/328048.html
上一篇:當我在腳本下運行時,它拋出錯誤“行程無法訪問檔案,因為它正被另一個行程使用”
下一篇:從csv中添加數字
