在C#DataTable中每行有多个超时(日期时间)值

时间:2013-06-05 21:26:17

标签: c# datatable

我有一个DataTable,每行有多个TimeStamp(DateTime)列。我想创建一个超时值,所以当TimeStamp传递DateTime.Now-timeoutValue时,它将被取消。当所有TimeStamp值都为空时,该行将被删除。

目前使用定时器和循环实现。很多条目开始变得非常滞后,是否有更自动化的有效方式?表达式还是什么?以下是我的代码剪辑:

public ReadsList(object _readers)
{
    _readers = List of things that add to datatable
    dataTable = new DataTable();
    Timeout = 5;

    aTimer = new System.Timers.Timer(5000);
    aTimer.Elapsed += new ElapsedEventHandler(UpdateReads);
    aTimer.Enabled = true;
}

public void Add(object add)
{
    //Checks if object exists, update TimeStamp if so, else, add new row
}

private void UpdateReads(object source, ElapsedEventArgs e)
{
    //Clean DataTable
    foreach (DataRow row in dataTable.Rows.Cast<DataRow>().ToList())
    {
         int p = 0;
         foreach (var i in _readers)
         {
             p += i.Value;

             for (int b = 1; b <= i.Value; b++)
             {
                 if (row[(i.Key + ":" + b)] != DBNull.Value)
                 {
                     if (Timeout == 0)
                         Timeout = 99999;
                     if (DateTime.Parse(row[(i.Key + ":" + b)].ToString()) <
                         DateTime.UtcNow.AddSeconds(-1*Timeout))
                     {
                         row[(i.Key + ":" + b)] = DBNull.Value;
                     }    
                 }
                 else
                 {
                       p -= 1;
                 }
             }

        }
             //Remove Row if empty
             if (p == 0)
             {
                row.Delete();
                //readCount -= 1;
             }
        }
     dataTable.AcceptChanges();
     OnChanged(EventArgs.Empty);
}

2 个答案:

答案 0 :(得分:1)

以下是一些小改进的想法,可能会带来显着的改善:

  1. 您不止一次构建了列键(i.Key + ":" + b)。在内部foreach内构建一次并将其粘贴在变量中。
  2. 您正在多次阅读专栏(row[(i.Key + ":" + b)])。读一次并将其粘贴在一个变量中,以便您可以多次使用它,而不必每次都进行哈希表查找。
  3. 您正在多次调整超时(if (Timeout == 0) Timeout = 99999;)。在方法开始时调整一次。
  4. 您不止一次计算超时DateTime(DateTime.UtcNow.AddSeconds(-1*Timeout))。在方法开始时计算一次。
  5. 您总是按字符串查找列值。如果您可以将列序列存储在某处并使用它们,那么您将获得更好的性能。只需确保在方法开头一次查找列序号,而不是在foreach es中查找。
  6. 您正在将字符串解析为DateTimes。如果您可以在DataTable中存储DateTimes,则不必每次都进行解析。

答案 1 :(得分:0)

首先,您可以在此处执行一些操作来提高速度。首先,数据表用于从数据库中提取数据,而不是真正的高端集合。通常,通用列表比数据表快4倍,并且使用的内存要少得多。此外,您的最大时间成本来自第三个循环中间的DateTime.Parse,并在循环中间执行DateTime计算到期时间。它没有出现过期时间是基于记录的原始值,所以你应该在循环开始之前产生一次。

我建议为您的记录格式创建一种数据类型,这样您就可以将记录日期存储为DateTime对象,基本上消耗了首次初始化列表时的转换时间,而不是每次都执行tryparse。因此,使用List来存储数据,您可以简单地执行以下操作:

var cutOffTime = DateTime.UtcNow.AddSeconds(-99999); // Do this to save creating it a billion times.
var totalRecords = AllRecords.Count; // Do this so the value is not re-evaluated

for(var i=0;i<totalRecords;i++)
{
   var rec = AllRecords[i];

   if(rec.TimeThingy1 < CutOffTime && rec.TimeThingy2 < cutOffTime && rec.TimeThingy3 < cutOffTime)    
    {
      AllRecords.RemoveAt(i); // You could even add this to another list, and remove all at the end, as removing an object from a list during mid-iteration is costly
    } 
}