如何在有限的时间内将变量保存在动态数组中

How to keep variables in dynamic array for a limited time

我有一个 c# winforms 应用程序,它从某些网页下载内容并将其放入一个名为 content 的字符串变量中。然后在content中搜索特定的关键字(包含在一个字符串中,用逗号分隔),如果匹配则发出警报;否则,发出另一个网络请求并再次运行搜索。

我的客户提出了一些不同的要求:他希望程序在找到关键字并触发警报后继续运行,但这次它应该只查找最近 5 分钟内未找到的剩余关键字。

我考虑过将找到的关键字添加到一个名为 foundKeywordsList 的动态数组中,并在 5 分钟后启动秒表或某种计时器将它们从数组中删除,但我不知道如何做到这一点,所以这是我的问题。到目前为止,这是相关代码(它在循环内运行):

List<string> foundKeywordsList = new List<string>();

string keywords = "scott,mark,tom,bob,sam";

string[] keywordArray = keywords.Split(',');

foreach (string kw in keywordArray)
{
    // Performs search only if the keyword wasn't found in the last 5 minutes
    if (!foundKeywordsList.Contains(kw) && content.IndexOf(kw) != -1)
    {
        //
        // code for triggering the alarm
        //

        foundKeywordsList.Add(kw);
    }
}

谢谢大家。

可能更好的方法是创建一个 Dictionary<string, DateTime>,在其中添加找到的关键字和找到它的时间。然后创建一个通过计时器调用的方法,主体为:

foundKeywordsDict = foundKeywordsDict.Where(kvp => kvp.Value > DateTime.Now.AddMinutes(-5))
                    .ToDictionary(kvp => kvp.Key, kvp = > kvp.Value)

这样做的目的是根据现有词典创建一个新词典,其中所有关键字都是在过去 5 分钟内添加的。

编辑: c#中有两种定时器,System.Timers.TimerSystem.Threading.Timer。以下是使用后者。使用 System.Threading.TimerTimer 将在计时器命中时创建一个新线程,调用您在构造函数中传递的 TimerCallback 委托,并重新启动计时器。 TimerCallback 只接受签名为 void MethodName(object state) 的方法(它可以是静态的)。

对于您的情况,您希望您的代码看起来类似于:

public void RemoveOldFoundKeywords(object state)
{
    lock(foundKeywordsDict) //since you are working with threads, you need to lock the resource
        foundKeywordsDict = foundKeywordsDict.Where(kvp => kvp.Value > DateTime.Now.AddMinutes(-5))
                    .ToDictionary(kvp => kvp.Key, kvp = > kvp.Value)
}

要创建计时器,您需要类似这样的东西:

Using System.Threading;
....

int timerInterval = 60*1000 //one minute in milliseconds
TimerCallback timerCB = new TimerCallback(RemoveOldFoundKeywords);

Timer t = new Timer(
    timerCB,         //the TimerCallback delegate
    null,            //any info to pass into the called method
    0,               //amount of time to wait before starting the timer after creation
    timerInterval);  //Interval between calls in milliseconds

有关 System.Threading.Timer class 的更多信息,请参见 here, info for the System.Timers.Timer class can be found here and info for the lock keyword can be found here

如果你想定期清除foundKeywordsList,你可以试试这个:

// Invoke the background monitor
int _5mins = 5 * 60 * 1000;
System.Threading.Tasks.Task.Factory.StartNew(() => PeriodicallyClearList(foundKeywordsList, _5mins));

// Method to clear the list
void PeriodicallyClearList(List<string> toClear, int timeoutInMilliseconds)
{
    while (true)
    {
        System.Threading.Thread.Sleep(timeoutInMilliseconds);
        toClear.Clear();
    }
}

您需要在访问 foundKeywordsList 时添加锁块,以确保添加和清除不会同时发生。