首页 > 解决方案 > Filewatcher 队列管理

问题描述

我有一个文件监视程序正在监视文件更改的目录。当它发生时,每个文件都在由 FileProcessor 类(带有线程)管理的队列中排队。我想在一个标签中更新 Form1 中 Q 中的文件数(每次更新该数字)我尝试了几件事,包括:

class FileProcessor : IDisposable
{
   private static Form1 frm;

以及稍后在课堂上的电话:

frm.Invoke((MethodInvoker)delegate { frm.button4.Text = Qcounte(); });

我有一个 System.NullReferenceException 因为我不知道如何在 frm 中声明 Form1 :(

这是带有更新标签功能的主表单:SetQ(string s)

public delegate void ddisplayQ(string q);
public partial class Form1 : Form
{
    public static ddisplayQ deldisplayQ;
public Form1()
    {
        InitializeComponent();
        deldisplayQ = new ddisplayQ(this.setQ);
    }
private void setQ(string s)
    {
        button4.Text = s;
    }

在 FileProcessor 类上,这是我调用标签更新的方式:

Form1.deldisplayQ.Invoke(Qcounte());

public string Qcounte()
    {
        return Convert.ToString(fileNamesQueue.Count);
    }

            Form1.deldisplayQ.Invoke(Qcounte());

这是整个班级:

 class FileProcessor : IDisposable
{
    private EventWaitHandle eventWaitHandle = new AutoResetEvent(false);
    private Thread worker;
    private readonly object locker = new object();
    private Queue<string> fileNamesQueue = new Queue<string>();
    public static Form1 frm ;
     public FileProcessor()
    {
        worker = new Thread(Work);
        worker.Start();
    }

    public void EnqueueFileName(string FileName)
    {
        lock (locker) fileNamesQueue.Enqueue(FileName);
        eventWaitHandle.Set();
    }
    private void Work()
    {
        while (true)
        {
            string fileName = null;
            lock (locker)
                if (fileNamesQueue.Count > 0)
                {
                    if (fileName == null) return;
                }
            if (fileName != null)
            {
                ProcessFile(fileName);
            }
            else
            {
                eventWaitHandle.WaitOne();
            }
        }
    }
    private void ProcessFile(string FileName)
    {
        Globals.getTags(FileName);
        Globals.ecritDb(FileName);
    }
    public string Qcounte()
    {
        return Convert.ToString(fileNamesQueue.Count);
    }
    #region IDisposable Members

    public void Dispose()
    {
        EnqueueFileName(null);
        worker.Join();
        eventWaitHandle.Close();
    }

    #endregion
}

我的问题是:在哪里触发 FileProcessor 类中的入队和出队,以便我可以看到主窗体中文件处理的增加和减少?提前致谢

标签: c#

解决方案


代码对我来说看起来并不完整,但这里有一些你应该做的事情:

  1. 在 FileProcessor 中,您有一个 Form 的引用。我的假设是只有 1 个正确的表单实例?所以添加public static Form1 Instance { get; set; }到 Form1 类。在窗体的构造函数中设置它。

    public partial class Form1 : Form
    {
       public static Form1 Instance { get; set; }
    
       public Form1()
       {
         InitializeComponent();
         Instance = this;
       }
    
       public void UpdateText(string text)
       {
         BeginInvoke(  new Action( () =>
         {
           button4.Text = text;
         }));
        }
    
  2. 所以回到FileProcessor,去掉Form的实例变量。要在 Form 上调用文本框的 UI 更新,只需将 Form 类上的方法添加为实例方法。唯一的区别是使用BeginInvoke() 这很重要,因为 FileProcessor 在不同的线程上运行,并且无法更改任何 UI 控件。

    private void ProcessFile(string FileName)
    {
       Globals.getTags(FileName);
       Globals.ecritDb(FileName);
    
       //update UI
       Form1.Instance.UpdateText("hello");
    }
    

如何使用 BeginInvoke C#

当然,我们可以在这里使用接口或抽象来代替直接访问表单,但有时简单就足够了。


推荐阅读