0

这是我第一次尝试编写非基于 Web 的程序,也是我第一次用 C# 编写任何东西。

我需要一个监视文件夹的程序,但我无法让它工作。我已经使用了这篇文章中的示例Using FileSystemWatcher with multiple files,但正试图使其成为一个表单。

我当前的问题出现在 ProcessQueue 函数中,其中 fileList 显然是在另一个线程中定义的。每当文件实际提交到监视文件夹时,我都会收到一个错误,即使用 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 回答