close

最近公司的專案遇到需要再別人將資料新增之指定資料夾時,做讀資料的判斷工作。

在處裡的過程遇到監控資料夾的問題,以及讀檔案時遇到多執行序的問題,所以來分享一下我的方法。

首先,先大概拉個介面,以下的程式中會包含程式檔名、資料夾下檔案數量。

監控視窗.PNG

在這裡只做讀到檔案名稱及檔案數量的工作(我工作上遇到的是圖檔,所以還得開圖處理,如果之後有遇到其他問題,解決後會再發上來)。

然後是Code的部分

using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace listenFileFormApp
{
    public partial class Form1 : Form
    {
        
        StringBuilder sb;
        DirectoryInfo dirInfo;
        FileSystemWatcher _watch = new FileSystemWatcher();


        public Form1()
        {
            InitializeComponent();
            MyFileSystemWatcher();
        }

        private void MyFileSystemWatcher()
        {
            
            //設定欲監控之資料夾位置
            _watch.Path = @"F:\測試區\IN";

            //設定欲監控的變更類型
            _watch.NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName;

            //設定欲監控的檔案
            _watch.Filter = "*.jpg";

            //設定是否監控子資料夾
            _watch.IncludeSubdirectories = true;

            //設定是否啟動元件,此部分必須要設定為 true,不然事件是不會被觸發的
            _watch.EnableRaisingEvents = true;

            //設定觸發事件
            _watch.Created += new FileSystemEventHandler(_watch_Created);
        }
               
        /// <summary>
        /// 當所監控的資料夾有建立文字檔時觸發
        /// </summary>
        private void _watch_Created(object sender, FileSystemEventArgs e)
        {
            sb = new StringBuilder();

            dirInfo = new DirectoryInfo(e.FullPath.ToString());

            //使用 delegate + invoke 方式跨執行緒對label進行操作
            setlbFileName(dirInfo.Name);
            setLbFileAmount(dirInfo.Parent.GetFiles().Count().ToString());
            
        }

        public delegate void SetTextCallback(string s);

        /// <summary>
        /// 使用 delegate + invoke 方式跨執行緒對label進行操作
        /// </summary>
        /// <param name="text"></param>
        private void setlbFileName(string text)
        {
            if (this.lb_fileName.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(setlbFileName);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.lb_fileName.Text = text;
            }
        }

        /// <summary>
        /// 使用 delegate + invoke 方式跨執行緒對label進行操作
        /// </summary>
        /// <param name="text"></param>
        private void setLbFileAmount(string text)
        {
            if (this.lb_fileAmount.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(setLbFileAmount);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.lb_fileAmount.Text = text;
            }
        }


    }
}

執行時只要往指定的資料夾內丟檔案,就會觸發監控Function。

 

在做檔案監控的部分其實沒遇到甚麼大問題,主要是要將資訊顯示在label時遇到多執行序的問題。

一開始我的寫法是這樣(看第七行)

        private void _watch_Created(object sender, FileSystemEventArgs e)
        {
            sb = new StringBuilder();

            dirInfo = new DirectoryInfo(e.FullPath.ToString());

            lb_fileName.Text = dirInfo.Name;
            
        }

就遇到了錯誤訊息【System.InvalidOperationException: '跨執行緒作業無效: 存取控制項 'lb_fileName' 時所使用的執行緒與建立控制項的執行緒不同。'】

後來的解決方法就是使用 delegate + invoke 方式跨執行緒對label進行操作,

在查解決方案時,有查到另一種解決方案,是直接設定不檢查多執行序問題的方法。如下:

Form.CheckForIllegalCrossThreadCalls = false;

這方法在DEBUG開發的過程會方便很多,但真正給使用者執行時,似乎不是最安全的方法。

看來在之後還得多學習一些關於跨執行序的問題了。

說到這,因為之後監控的資料夾不會只有一個,所以當必須監控多個資料夾的情況時,建議為欲監督的每個資料夾都各建立一個FileSystemWatcher,但是讓所有的FileSystemWatcher都共用相同的事件處理程序

 


好了,以上是小弟個人的關於資料夾監控的程式撰寫心得,給大家參考,如有誤人子弟之處,還請各位先進給予指教。

如果覺得本篇文章對你有幫助的話,也請別忘記留言給予鼓勵喔。

 

 

 

 

 

arrow
arrow

    zhong.jun.jimmy 發表在 痞客邦 留言(1) 人氣()