C# Filewatcher队列管理

C# Filewatcher队列管理,c#,C#,我有一个filewatcher,它正在监视目录中的文件更改。 发生这种情况时,每个文件都在一个由FileProcessor类(带有线程)管理的队列中排队。 我想在表格1中更新Q中文件的数量(每次更新该数量时) 我尝试了几件事,包括: class FileProcessor : IDisposable { private static Form1 frm; 以及稍后在课堂上的调用: frm.Invoke((MethodInvoker)delegate { frm.button4.Text

我有一个filewatcher,它正在监视目录中的文件更改。 发生这种情况时,每个文件都在一个由FileProcessor类(带有线程)管理的队列中排队。 我想在表格1中更新Q中文件的数量(每次更新该数量时) 我尝试了几件事,包括:

class FileProcessor : IDisposable
{
   private static Form1 frm;
以及稍后在课堂上的调用:

frm.Invoke((MethodInvoker)delegate { frm.button4.Text = Qcounte(); });
我有一个System.NullReferenceException,因为我不知道如何在frm中声明Form1:(

下面是带有更新标签的函数的主窗体:SetQ(字符串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
}
类文件处理器:IDisposable
{
private EventWaitHandle EventWaitHandle=new AutoResetEvent(false);
私人线程工作者;
私有只读对象锁定器=新对象();
专用队列fileNamesQueue=新队列();
公共静态表格1 frm;
公共文件处理器()
{
工人=新线程(工作);
worker.Start();
}
public void排队文件名(字符串文件名)
{
lock(locker)fileNamesQueue.Enqueue(FileName);
eventWaitHandle.Set();
}
私人工作()
{
while(true)
{
字符串文件名=null;
锁(储物柜)
如果(fileNamesQueue.Count>0)
{
如果(fileName==null)返回;
}
如果(文件名!=null)
{
进程文件(文件名);
}
其他的
{
eventWaitHandle.WaitOne();
}
}
}
私有void进程文件(字符串文件名)
{
getTags(文件名);
Globals.ecritDb(文件名);
}
公共字符串Qcounte()
{
返回Convert.ToString(fileNamesQueue.Count);
}
#区域IDisposable成员
公共空间处置()
{
排队文件名(空);
worker.Join();
eventWaitHandle.Close();
}
#端区
}
我的问题是: 在哪里触发FileProcessor类中的排队和出列,以便在我的主窗体中看到文件处理的增加和减少?
提前感谢

在我看来,代码并不完整,但以下是您应该做的一些事情:

  • 从FileProcessor中,您有一个表单的引用。我的假设是表单只有一个实例。正确吗?因此,将
    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;
         }));
        }
    
  • 因此回到FileProcessor,删除表单的实例变量。要调用表单上文本框的UI更新,只需将表单类上的方法添加为实例方法。唯一的区别是使用
    BeginInvoke()
    这很重要,因为FileProcessor运行在不同的线程上,无法更改任何UI控件

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

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

    哇,谢谢!当我通过公共void UpdateText(字符串文本)时,我有一个例外:无法将lambda表达式转换为“Delegate”类型,因为它不是委托类型。我修改了UpdateText方法,复制它,然后重试。是的,通过阅读您提供的链接,我发现了这一点…谢谢,委托工作得很好(谢谢),队列管理不好(或者太快)。我将调查队列是否存在事件。
    private void ProcessFile(string FileName)
    {
       Globals.getTags(FileName);
       Globals.ecritDb(FileName);
    
       //update UI
       Form1.Instance.UpdateText("hello");
    }