0

これは、Webベースではないプログラムを作成するのは初めてであり、C#で何かを作成するのは初めてです。

フォルダを監視するプログラムが必要ですが、動作させることができません。この投稿の例を複数のファイルでFileSystemWatcherを使用して使用しましたが、フォームにしようとしています。

私の現在の問題は、fileListが明らかに別のスレッドで定義されているProcessQueue関数にあります。ファイルが実際に監視対象フォルダーに送信されるたびに、fileListの使用はクロススレッド呼び出しであるというエラーが発生します

誰かがこのエラーを私に説明できますか、そしてそれを修正する方法はありますか?

namespace matasWatch
{
    public partial class Form1 : Form
    {
        private int n = 1;
        private bool isWatching = false;
        private List<string> filePaths;
        private System.Timers.Timer processTimer;
        private string watchedPath;
        private FileSystemWatcher watcher;

        public Form1()
        {
            filePaths = new List<string>();
            watchedPath = "C:\\Users\\username\\Desktop\\test";
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (!isWatching)
            {
                button1.Text = "Stop";
                isWatching = true;
                watcher = new FileSystemWatcher();
                watcher.Filter = "*.*";
                watcher.Created += Watcher_FileCreated;
                watcher.Error += Watcher_Error;
                watcher.Path = watchedPath;
                watcher.IncludeSubdirectories = true;
                watcher.EnableRaisingEvents = true;
            }
            else {
                button1.Text = "Watch";
                isWatching = false;

                watcher.EnableRaisingEvents = false;
                watcher.Dispose();
                watcher = null;
            }
        }

        private void Watcher_Error(object sender, ErrorEventArgs e)
        {
            // Watcher crashed. Re-init.
            isWatching = false;
            button1_Click(sender, e);
        }

        private void Watcher_FileCreated(object sender, FileSystemEventArgs e)
        {
            filePaths.Add(e.FullPath);

            if (processTimer == null)
            {
                // First file, start timer.
                processTimer = new System.Timers.Timer(2000);
                processTimer.Elapsed += ProcessQueue;
                processTimer.Start();
            }
            else{
                // Subsequent file, reset timer.
                processTimer.Stop();
                processTimer.Start();
            }
        }

        private void ProcessQueue(object sender, ElapsedEventArgs args)
        {
            try
            {
                fileList.BeginUpdate();
                foreach (string filePath in filePaths)
                {
                    fileList.Items.Add("Blaa");
                }
                fileList.EndUpdate();
                filePaths.Clear();
            }
            finally
            {
                if (processTimer != null)
                {
                    processTimer.Stop();
                    processTimer.Dispose();
                    processTimer = null;
                }
            }
        }
    }
}
4

2 に答える 2

1

fileListはWindowsフォームコントロールだと思います。ProcessQueueメソッドは、デフォルトでバックグラウンドスレッドであるタイマースレッドから呼び出されます。fileListコントロールはUIスレッドにあります。フォームのInvoke()メソッドを使用して、それをデリゲートに渡すと、fileListコントロールが更新されます。

    Invoke(new Action(() => 
    { 
        fileList.BeginUpdate();
        foreach (string filePath in filePaths)
        {
            fileList.Items.Add("Blaa");
        }
        fileList.EndUpdate();
        filePaths.Clear();    
    }));
于 2012-10-25T09:42:34.873 に答える
0

System.Windows.Forms.Timer代わりにを使用しSystem.Timers.Timerて、タイマーティックイベントがUIスレッドで実行されるようにしてください。

詳細については、こちらをご覧ください。

于 2012-10-25T09:44:42.803 に答える