【问题标题】:Filewatcher queue managementFilewatcher 队列管理
【发布时间】:2020-03-06 18:16:44
【问题描述】:

我有一个文件监视程序,它正在监视目录中的文件更改。 当它发生时,每个文件都在由 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】:

    代码在我看来并不完整,但您应该执行以下操作:

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

      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");
      }
      

    How to use BeginInvoke C#

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

    【讨论】:

    • 哇,谢谢!当我通过公共 void UpdateText(string text) 时出现异常:无法将 lambda 表达式转换为类型“Delegate”,因为它不是委托类型
    • 我修改了UpdateText方法,复制一下再试。
    • 是的,我明白了,阅读您提供的链接......谢谢,代表工作得很好(谢谢),队列管理,不是(或者太快了)。我会调查是否有队列事件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-19
    • 2021-09-13
    • 2017-04-03
    相关资源
    最近更新 更多