การใช้ FileSystemWatcher เพื่อมอนิเตอร์ไดเร็กทอรี


104

ฉันใช้ Windows Forms Application เพื่อตรวจสอบไดเร็กทอรีและย้ายไฟล์ที่ทิ้งไว้ในไดเร็กทอรีอื่น

ในขณะนี้มันจะคัดลอกไฟล์ไปยังไดเร็กทอรีอื่น แต่เมื่อมีการเพิ่มไฟล์อื่นมันจะจบลงโดยไม่มีข้อความแสดงข้อผิดพลาด บางครั้งจะคัดลอกสองไฟล์ก่อนที่จะสิ้นสุดในไฟล์ที่สาม

นี่เป็นเพราะฉันใช้ Windows Form Application แทนที่จะเป็นแอปคอนโซลใช่หรือไม่ มีวิธีใดบ้างที่ฉันสามารถหยุดโปรแกรมไม่ให้สิ้นสุดและเฝ้าดูไดเร็กทอรีต่อไป

private void watch()
{
  this.watcher = new FileSystemWatcher();
  watcher.Path = path;
  watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                         | NotifyFilters.FileName | NotifyFilters.DirectoryName;
  watcher.Filter = "*.*";
  watcher.Changed += OnChanged;
  watcher.EnableRaisingEvents = true;
}

private void OnChanged(object source, FileSystemEventArgs e)
{
  //Copies file to another directory.
}

public void Dispose()
{
  // avoiding resource leak
  watcher.Changed -= OnChanged;
  this.watcher.Dispose();
}

คำตอบ:


147

ปัญหาคือตัวกรองการแจ้งเตือน โปรแกรมพยายามเปิดไฟล์ที่ยังคงคัดลอกอยู่ ฉันลบตัวกรองการแจ้งเตือนทั้งหมดยกเว้น LastWrite

private void watch()
{
  FileSystemWatcher watcher = new FileSystemWatcher();
  watcher.Path = path;
  watcher.NotifyFilter = NotifyFilters.LastWrite;
  watcher.Filter = "*.*";
  watcher.Changed += new FileSystemEventHandler(OnChanged);
  watcher.EnableRaisingEvents = true;
}

7
สวัสดีฉันใช้วิธีนี้ แต่เมื่อฉันคัดลอกไฟล์เหตุการณ์จะถูกเพิ่มขึ้นสองครั้ง: ครั้งหนึ่งเมื่อไฟล์ถูกสร้างว่างเปล่า (เริ่มการคัดลอก) และอีกครั้งเมื่อการคัดลอกเสร็จสิ้น จะหลีกเลี่ยงเหตุการณ์ที่ซ้ำกันนี้ได้อย่างไรตัวกรองใด ๆ ที่สามารถจัดการได้โดยไม่ต้องมีการควบคุมแบบกำหนดเอง
dhalfageme

@dhalfageme ฉันตรวจสอบทั้งสองเหตุการณ์ว่ามีสิ่งใดที่มีความหมายสำหรับแอปพลิเคชันของฉันปรากฏในโฟลเดอร์หรือไม่
Eftekhari

30

คุณไม่ได้ระบุรหัสการจัดการไฟล์ แต่ฉันคิดว่าคุณทำผิดพลาดเหมือนกันที่ทุกคนทำเมื่อเขียนสิ่งนี้เป็นครั้งแรก: เหตุการณ์ filewatcher จะถูกยกขึ้นทันทีที่สร้างไฟล์ อย่างไรก็ตามจะต้องใช้เวลาสักพักกว่าไฟล์จะเสร็จสมบูรณ์ ยกตัวอย่างเช่นขนาดไฟล์ 1 GB โปรแกรมอื่นอาจสร้างไฟล์ขึ้นมา (Explorer.exe คัดลอกมาจากที่ไหนสักแห่ง) แต่จะใช้เวลาไม่กี่นาทีในการดำเนินการให้เสร็จสิ้น เหตุการณ์จะเพิ่มขึ้นในเวลาสร้างและคุณต้องรอให้ไฟล์พร้อมที่จะคัดลอก

คุณสามารถรอให้ไฟล์พร้อมได้โดยใช้ฟังก์ชันนี้ในการวนซ้ำ


26

สาเหตุอาจเป็นเพราะผู้เฝ้าดูถูกประกาศให้เป็นตัวแปรท้องถิ่นของเมธอดและเป็นขยะที่รวบรวมเมื่อเมธอดเสร็จสิ้น คุณควรประกาศเป็นสมาชิกชั้นเรียน ลองทำดังต่อไปนี้:

FileSystemWatcher watcher;

private void watch()
{
  watcher = new FileSystemWatcher();
  watcher.Path = path;
  watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                         | NotifyFilters.FileName | NotifyFilters.DirectoryName;
  watcher.Filter = "*.*";
  watcher.Changed += new FileSystemEventHandler(OnChanged);
  watcher.EnableRaisingEvents = true;
}

private void OnChanged(object source, FileSystemEventArgs e)
{
  //Copies file to another directory.
}

19
watcherตัวแปรยังคงมีชีวิตอยู่ (ไม่ใช่การเก็บขยะ) เนื่องจากเขาสมัครเป็นสมาชิกเหตุการณ์ที่เปลี่ยนแปลง
adospace

1
ผมเชื่อว่ามันเป็นจริงเพราะ EnableRaisingEvents trueมีการตั้งค่า ฉันไม่คิดว่าสถานะของตัวจัดการเหตุการณ์ของสมาชิกจะเกี่ยวข้องกับการรวบรวมขยะ ฉันคิดว่า EnableRaisingEvents มีสิ่งที่ฉันควรเรียกว่าพฤติกรรมพิเศษในกรณีนี้
Matias Grioni
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.