[英]How to determine whether a folder has finished copying c#
我有一個問題:如何確定文件夾是否已完成從一個位置到另一個位置的復制?
目前,一旦復制目錄中的文件,我的FileSystemWatcher就會觸發多個事件。 我想要的是,成功復制該文件夾中的所有文件后將觸發一個事件。 我的代碼現在看起來像這樣:
static void Main(string[] args)
{
String path = @"D:\Music";
FileSystemWatcher mWatcher = new FileSystemWatcher();
mWatcher.Path = path;
mWatcher.NotifyFilter = NotifyFilters.LastAccess;
mWatcher.NotifyFilter = mWatcher.NotifyFilter | NotifyFilters.LastWrite;
mWatcher.NotifyFilter = mWatcher.NotifyFilter | NotifyFilters.DirectoryName;
mWatcher.IncludeSubdirectories = true;
mWatcher.Created += new FileSystemEventHandler(mLastChange);
mWatcher.Changed += new FileSystemEventHandler(mLastChange);
mWatcher.EnableRaisingEvents = true;
Console.WriteLine("Watching path: " + path);
String exit;
while (true)
{
exit = Console.ReadLine();
if (exit == "exit")
break;
}
}
private static void mLastChange(Object sender, FileSystemEventArgs e)
{
Console.WriteLine(e.ChangeType + " " + e.FullPath);
}
不幸的是,FileSystemWatcher不會告訴您文件何時完成寫入。 所以你的選擇是...
重新閱讀您的問題后,聽起來您對其他應用程序沒有任何控制權。
因此,您將需要某種超時值來確定何時完成所有寫入。 基本上創建一個計時器,該計時器在每個filesystemwatcher事件發生后重置...當它超時時,您將觸發一個表明已完成的事件。
這是將其添加到代碼中的方法...
static void Main(string[] args)
{
Timer.Interval = 5000; // 5 seconds - change to whatever is appropriate
Timer.AutoReset = false;
Timer.Elapsed += TimeoutDone;
String path = @"D:\Music";
FileSystemWatcher mWatcher = new FileSystemWatcher();
mWatcher.Path = path;
mWatcher.NotifyFilter = NotifyFilters.LastAccess;
mWatcher.NotifyFilter = mWatcher.NotifyFilter | NotifyFilters.LastWrite;
mWatcher.NotifyFilter = mWatcher.NotifyFilter | NotifyFilters.DirectoryName;
mWatcher.IncludeSubdirectories = true;
mWatcher.Created += new FileSystemEventHandler(mLastChange);
mWatcher.Changed += new FileSystemEventHandler(mLastChange);
mWatcher.EnableRaisingEvents = true;
Console.WriteLine("Watching path: " + path);
Timer.Start();
String exit;
while (true)
{
exit = Console.ReadLine();
if (exit == "exit")
break;
}
}
private static Timer Timer = new Timer();
private static void TimeoutDone(object source, ElapsedEventArgs e)
{
Console.WriteLine("Timer elapsed!");
}
private static void mLastChange(Object sender, FileSystemEventArgs e)
{
Console.WriteLine(e.ChangeType + " " + e.FullPath);
if (Timer != null)
{
Timer.Stop();
Timer.Start();
}
}
太俗氣了,但過去我通過為FileSystemWatcher類創建自定義裝飾器來解決此問題。 在內部,它創建一個FileSystemWatcher並注冊Created和Changed事件,包裝它們,並在文件完成后拋出自己的Created和Changed事件,類似於:
private void Watcher_Changed(Object sender, FileSystemEVentArgs e)
{
while (true)
{
FileStream stream;
try
{
stream = File.Open(e.FullPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
// If this succeeds, the file is finished
Changed();
}
catch (IOException)
{
}
finally
{
if (stream != null) stream.Close();
}
}
}
其中一些是從這里的答案中得出的。 實際上,您不應該使用無限循環。 您可能想要添加超時,在兩次檢查之間睡眠,等等,但這是一般的想法。
如果目標是本地文件夾,則可以使用文件系統過濾器驅動程序來跟蹤文件創建和文件關閉事件。 知道所有先前創建的文件何時關閉將通知您復制已完成。
我用一個擴展FileSystemWatcher
的類創建了一個Git存儲庫,使其僅在復制完成后才觸發事件。
下載FileSystemSafeWatcher並將其添加到您的項目中。
然后將其用作普通的FileSystemWatcher
並監視何時觸發事件。
var fsw = new FileExamSystemWatcher(file);
fsw.EnableRaisingEvents = true;
// Add event handlers here
fsw.Created += fsw_Created;
不幸的是,還沒有現成的解決方案。 但是我設計了一個簡單的棘手解決方案來觸發(復制完成)事件。
您應該使用計時器。
FileSystemWatcher fsw = new FileSystemWatcher();
string fullPath = "";
DateTime tempTime;
fsw.Path = @"C:\temp";
private void startwatching()
{
timer1.Start();
}
fsw.EnableRaisingEvents = true;
fsw.Created += Fsw_Created;
private void Fsw_Created(object sender, FileSystemEventArgs e)
{
tempTime = DateTime.Now.AddSeconds(-4);
fullPath = e.FullPath;
}
private void timer1_Tick(object sender, EventArgs e)
{
if (fullPath!=string.Empty)
{
timer1.Stop();
if (tempTime >= Directory.GetLastAccessTime(fullPath))
{
DirectoryInfo di = new DirectoryInfo(fullPath);
listBox1.Items.Add("Folder " + di.Name + " finished copying");
fullPath = string.Empty;
}
else
{
tempTime = DateTime.Now;
}
timer1.Start();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.