c# - 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 类中的入队和出队,以便我可以看到主窗体中文件处理的增加和减少?提前致谢
解决方案
代码对我来说看起来并不完整,但这里有一些你应该做的事情:
在 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; })); }
所以回到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"); }
当然,我们可以在这里使用接口或抽象来代替直接访问表单,但有时简单就足够了。
推荐阅读
- caddy - 美居 symfony 和 Caddy 服务器不工作
- django - 带有参数的Django url,不知道如何测试
- security - 保护客户端 Chrome 扩展代码的方法
- java - 如何在 Java 11 中检查MemberAccess(SomeClass.class, Member.DECLARED)
- php - 用于 Twitter 推文的 PHP 中带有 preg_replace 的 JSON 解码数组
- python - 正确排序字符串列表的问题
- regex - 正则表达式:排除主要搜索词在中间的短语
- jdbc - java.lang.ClassNotFoundException: jdbc:mysql 异常
- cassandra - 压缩导致内存不足错误并关闭 Cassandra 进程
- javascript - 柴东西使以前的测试失败?