Winforms中的两个线程任务不断回头

我目前正在尝试在本地文件夹的C#上保留一个计数器,以用于创建的新文件。

我必须对CD和LP的两个子目录进行检查。使用计数器可确保所创建的文件夹数不超过用户设置的数。

public static int LPmax { get; set; }
public static int CDmax { get; set; }

public static int LPcounter2 { get; set; }
public static int CDcounter2 { get; set; } 

public static int LPCreated;
public static int CDCreated;
public static int oldLPCreated;
public static int oldCDCreated;

FileSystemWatcher CDdirWatcher = new FileSystemWatcher();
FileSystemWatcher LPdirWatcher = new   FileSystemWatcher();
//watch method should run in the background as checker
public void watch()
{ 
        CDdirWatcher.Path = @"C:\Data\LotData\CD";
        CDdirWatcher.Filter = "EM*";
        CDdirWatcher.NotifyFilter = NotifyFilters.DirectoryName | NotifyFilters.LastWrite;
        CDdirWatcher.EnableRaisingEvents = true;
        CDdirWatcher.Created += CDdirWatcher_Created;


        LPdirWatcher.Path = @"C:\Data\LotData\LP";
        LPdirWatcher.Filter = "EM*";
        LPdirWatcher.NotifyFilter = NotifyFilters.DirectoryName;
        LPdirWatcher.EnableRaisingEvents = true;
        LPdirWatcher.Created += LPdirWatcher_Created;
        Thread.Sleep(10); 
}
private static void CDdirWatcher_Created(object sender,FileSystemEventArgs e)
{ 
    CDCreated += 1;
}
private static void LPdirWatcher_Created(object sender,FileSystemEventArgs e)
{ 
    LPCreated += 1;
}

上述方法效果很好,标准是计数必须少于一组。

public void checker()
{
    if(CDCreated>CDmax)
    {
        popupbx();
    }
    if(LPCreated>LPmax)
    {
        popupbx();
    }
}

问题是我的主要方法,我有两个线程,需要连续检查两个条件以查看计数器是否已超出。

public Form1()
{
    InitializeComponent();

    //Implementing Threads asynchronously
    Thread oThreadone = new Thread(() =>
    {
        //Do what u wanna……
        watch();
    });

    Thread oThreadtwo = new Thread(() =>
    {
        //Do what u wanna……
        checker();
    });

    //Calling thread workers
    oThreadone.Start(); 
    oThreadone.IsBackground = true; 
    oThreadtwo.Start();
    oThreadtwo.IsBackground = true;
}

Mkdir在调试模式下触发计数器,但是线程2在触发后不检查计数器。

leavewinter 回答:Winforms中的两个线程任务不断回头

您的代码的第一大错误是既不需要创建的线程,也不需要它们执行您想要的操作。具体来说,FileSystemWatcher对象本身已经是异步的,因此您可以在主线程中创建它。实际上,您应该这样做,因为在那里您可以将FileSystemWatcher.SynchronizingObject设置为当前表单实例,以便它将在该对象的同步上下文中引发其事件。即您的事件处理程序将在您想要的主线程中执行。

因此,第一种方法watch()不是直接在线程中执行,而是直接调用它。

这将我带到第二种方法checker()。您的线程方法不会循环,因此它将执行两个测试,然后立即退出。那是该线程的结尾。在更新计数时,它的停留时间不足以监视计数。

您可以通过循环checker()方法来修复它,以使其永远不会退出。但是随后您会遇到CPU使用率过高的问题。您可以通过添加sleep语句来解决该问题。那么您大部分时间都在浪费线程。您可以使用async / await(例如await Task.Delay())来解决。否则只会不必要地使代码复杂化。

相反,您应该在更新每个计数后执行每个检查。从理论上讲,您可以立即显示消息。但这将阻止预订到FileSystemWatcher的事件处理程序,可能会延迟其他报告。因此,您可能更喜欢使用Control.BeginInvoke()将消息的显示推迟到事件处理程序返回之后。

因此,考虑到所有这些,您的代码可能看起来更像这样:

public Form1()
{
    InitializeComponent();

    watch();
}

private void CDdirWatcher_Created(object sender,FileSystemEventArgs e)
{ 
    CDCreated += 1;
    if (CDCreated > CDmax)
    {
        BeginInvoke((MethodInvoker)popupbx);
    }
}

private static void LPdirWatcher_Created(object sender,FileSystemEventArgs e)
{ 
    LPCreated += 1;
    if (LPCreated > LPmax)
    {
        BeginInvoke((MethodInvoker)popupbx);
    }
}

您可以完全删除checker()方法。 watch()方法可以保持原样,尽管我将更改Created事件的订阅顺序和EnableRaisingEvents的分配顺序。即在您已订阅活动之前,请勿启用引发活动。 FileSystemWatcher确实不够可靠,没有让您有机会在准备观察事件之前就引发事件。 :)

这是基于您当前的实现。但是请注意,如果继续创建文件,则会反复显示该消息。如果它们创建得足够快,则在用户可以关闭以前显示的消息之前,将显示新消息。您可能希望修改代码以防止这种情况。例如。超过最大数量后,请取消订阅该事件,或者至少在已显示一条这样的消息时暂时禁止显示该消息。确切地,做什么取决于您,超出了您的问题范围,也超出了此答案的范围。

本文链接:https://www.f2er.com/3162021.html

大家都在问