基于FileSystemWatcher事件显示表单

问题描述

我正在出于教育目的创建Windows窗体应用程序,它的基本思想是拥有一个下载管理器,该管理器会将文件认的Downloads文件夹移动到带有文件扩展名的文件夹。我创建了MyFileWatcher类,该类基本上监视Downloads文件夹中是否有新文件代码如下:

public class MyFileWatcher
    {
        private readonly FileSystemWatcher _fileSystemWatcher;

        public MyFileWatcher()
        {

            _fileSystemWatcher = new FileSystemWatcher(resources.sourcePath);
            _fileSystemWatcher.Created += (sender,e) => _fileWatcher_Created(sender,e);

            _fileSystemWatcher.EnableRaisingEvents = true;
        }

        private void _fileWatcher_Created(object sender,FileSystemEventArgs e)
        {
            //calls class FileManager's function MoveFiles (here is base logic of how and where files should move)
            CustomServiceContainer.GetService<IFileManager>().MoveFiles(resources.sourcePath,resources.targetPath);

            //this is the problem
            Notification_form ntf = new Notification_form();
            ntf.showAlert(eventType);
        }
    }

问题是,当_fileWatcher_Created事件调用通知窗体时,什么都没有显示(即使我可以在任务栏上看到创建了窗口的窗口),我也不明白为什么,原因是如果我将showAlert函数分配给按钮的click事件,它将显示通知正确。

如果需要,这是“通知”表单的外观:

public partial class Notification_form : Form
    {
        private int x { get; set; }
        private int y { get; set; }

        public Notification_form()
        {
            InitializeComponent();
        }

        public enum enmAction { wait,start,close }

        private Notification_form.enmAction action;

        public void showAlert(string msg)
        {
            this.Opacity = 0.0;
            this.StartPosition = FormStartPosition.Manual;
            string fName;

            for (int i = 1; i < 10; i++)
            {
                fName = "alert" + i.ToString();
                Notification_form frm = (Notification_form)Application.OpenForms[fName];

                if (frm == null)
                {
                    this.Name = fName;
                    this.x = Screen.PrimaryScreen.WorkingArea.Width - this.Width + 15;
                    this.y = Screen.PrimaryScreen.WorkingArea.Height - this.Height * i;
                    this.Location = new Point(this.x,this.y);
                    break;
                }
            }

            this.x = Screen.PrimaryScreen.WorkingArea.Width - base.Width - 5;

            this.lblTitle.Text = msg;

            this.Show();
            this.action = enmAction.start;
            this.timer1.Interval = 1;
            this.timer1.Start();
        }

        private void timer1_Tick(object sender,EventArgs e)
        {
            switch (this.action)
            {
                case enmAction.wait:
                    timer1.Interval = 5000;
                    action = enmAction.close;
                    break;
                case Notification_form.enmAction.start:
                    this.timer1.Interval = 1;
                    this.Opacity += 0.1;
                    if (this.x < this.Location.X)
                    {
                        this.Left--;
                    }
                    else
                    {
                        if (this.Opacity == 1.0)
                        {
                            action = Notification_form.enmAction.wait;
                        }
                    }
                    break;
                case enmAction.close:
                    timer1.Interval = 1;
                    this.Opacity -= 0.1;

                    this.Left -= 3;
                    if (base.Opacity == 0.0)
                    {
                        base.Close();
                    }
                    break;
            }
        }

        private void btnCloseNtf_Click(object sender,EventArgs e)
        {
            timer1.Interval = 1;
            action = enmAction.close;
        }
    }

解决方法

对于那些遇到相同问题的人,正如Jimi所说的,在这种情况下的主要问题是UI和FileSystemWatcher在不同的线程上工作,因此当我尝试从MyFileWatcher调用表单时,它并没有显示表单是由不同的线程制成的,我该如何解决?好吧,我在Form中设置FileSystemWatcher的SynchronizingObject(所有功劳归于Jimi),如下所示:fw._fileSystemWatcher.SynchronizingObject = this;其中fw是FileSystemWatcher对象,该对象在程序类的创建过程中被传递给表单(注意:重要的是传递以形成用于获取通知的对象(在这种情况下)

此外,创建文件并不意味着可以移动文件(就像Jimi所说的那样:)。通常,文件在下载过程中处于临时扩展名(tmp,crdownload或什至其他),因此您还需要检查文件更改,以确保您没有移动没有价值的临时文件,此外,随着文件的创建并多次更改了通知表单,甚至以为实际上创建一个文件后就需要触发它。那我该如何解决呢?好吧,我不知道它是否是最好的解决方案,但是我创建了一个新的文本文档,其中包含我要移动的所有扩展名类型,所以现在我要检查下载文件夹中文本文档中的扩展名,以及是否有一个匹配文件被移动,并且由于我不再寻找临时文件类型了,FileSystemWatcher实际上现在给我一个通知。 (而且您随时可以根据需要手动在文本文档中添加新文件类型,但我打算将该功能集成到应用中)

希望这对某人有帮助...