【问题标题】:Constantly Requesting and Collecting Data for a Certain Period of Time在一段时间内不断请求和收集数据
【发布时间】:2016-01-04 17:08:44
【问题描述】:

我需要通过发送命令然后读取结果,在 X 分钟内尽可能快地连续检索数据。我不确定以下代码是否有效或用于不断检索:

DateTime utcStartTime = DateTime.UtcNow;
        while (DateTime.UtcNow <= (utcStartTime.AddSeconds(recordTime)))                       //Run the read-write function for approximately the time specified
        {
            try
            {

                Write("Write.Request");                                 //Requests the data
                Pmeas = Read();                                         //Reads the returned string. String = "ReadError" if no result is found.
                                                                        //Note that the following error checker doesn't effect the speed of data collection at a millisecond level (already checked), and is therefore not the cause of any delay.
                if (String.IsNullOrEmpty(Pmeas))
                {
                    Pmeas = "ReadError";                                //Necessary due to an apparent overwrite caused by the read function - Tells the later output (outside of while loop) that Pmeas experienced a read error
                    DateTime utcTime = DateTime.UtcNow;                 //Get the current time in UTC seconds (may need correcting).
                    pArray[i] = (Pmeas + "\t" + utcTime.ToString("%d") + Environment.NewLine);    //Appends the Pmeas of each instance to a string array with a timestamp
                }
                else
                {
                    DateTime utcTime = DateTime.UtcNow;
                    pArray[i] = (Pmeas + "\t" + utcTime.ToString("%d") + Environment.NewLine);    //Appends the Pmeas of each instance to a string array with a timestamp
                }
                Pmeas = "ReadError";                                    //Reset Pmeas to prove in file that Pmeas experienced a read error
            }
            catch (Exception f)                                         //Catch an exception if try fails
            {
                Console.WriteLine("{0} Exception caught.", f);
            }
            i++;                                            //let i grow so that the array can also grow, plus have a variable already available for being having the string being written into a file (not part of question or code-in-question).
        }

请注意,所有变量,如 i、Pmeas 和 pArray 都是在循环之前预定义的(以防止错误),并且 UTC 应该以秒为单位(不确定当前的语法;具有十进制精度)。正如我所说,我正在寻找一种方法,该方法可以使用上面给出的读取和写入函数不断地从另一个来源收集数据,并在一段时间内不断地这样做而不会延迟。我的简单问题是,这是收集数据的正确方法还是有更好和/或更有效的方法?

欢迎对代码的所有输入,即使它没有完整回答问题。

【问题讨论】:

  • WriteRead 实际需要多长时间?上面发布的代码是否真的会导致可量化的速度问题 - 例如,如果这些方法比你包裹它们的代码慢一个数量级(例如),我不会担心......
  • 上面的当前代码(最初是在 for 循环中)有 17 毫秒的延迟。我们正试图将其降低到至少一半,但我们仍然需要每个数据点的时间戳。
  • @Midimistro 如果你想达到这个目标,你需要知道哪些代码行占用了这 17 毫秒的大部分时间,如果没有分析器,你就无法做到这一点。此外,DateTime 仅精确到大约 15 毫秒,要低于您需要切换到 Stopwatch,在开始时记录一个 DateTime,然后使用秒表计算已经过去了多少时间。当你去写你的输出时,从数据点的记录开始时间+时间跨度。

标签: c# loops datetime time constants


【解决方案1】:

字符串连接可能很慢,请尝试创建一个包含 DateTime 和字符串的类,并让 pArray 代替它。稍后在时间不重要时转换为字符串。也可以使用秒表来记录时长,DateTime 的最小分辨率约为 15ms。

//Declared elsewhere
public class DataPoint
{
    public TimeSpan Time {get; set;}
    public String Message {get; set;}
}


    List<DataPoint> dataPoints = new List<DataPoint>(pArray.Length); //make the default size the same as pArray so we don't waist time growing the list.

    Stopwatch duration = new Stopwatch();
    DateTime utcStartTime = DateTime.UtcNow;
    duration.Start();
    DateTime endTime = utcStartTime.AddSeconds(recordTime); //Move this out of the loop so it only does the calculation once.
    while (DateTime.UtcNow <= endTime)                       //Run the read-write function for approximately the time specified
    {
        try
        {

            Write("Write.Request");                                 //Requests the data
            Pmeas = Read();                                         //Reads the returned string. String = "ReadError" if no result is found.

            var dataPoint = new DataPoint
                {
                    Time = duration.Elapsed,
                    Message = Pmeas
                };
            dataPoints.Add(dataPoint);                                                     
            Pmeas = "ReadError";                                    //Reset Pmeas to prove in file that Pmeas experienced a read error
        }
        catch (Exception f)                                         //Catch an exception if try fails
        {
            Console.WriteLine("{0} Exception caught.", f);
        }
    }

    //Now that we are out of the time critical section do the slow work of formatting the data.
    foreach(var dataPoint in dataPoints)
    {
        var message = dataPoint.Message;
        if (String.IsNullOrEmpty(message))
        {
            message = "ReadError";
        }
        pArray[i] = message + "\t" + (utcStartTime + dataPoint.Time).ToString("%d") + Environment.NewLine;    //Appends the Pmeas of each instance to a string array with a timestamp

        i++;                                            //let i grow so that the array can also grow, plus have a variable already available for being having the string being written into a file (not part of question or code-in-question).
    }

但这可能是一个微小的变化,请获取一个分析器(visual studio comes with one,但我更喜欢使用DotTrace),看看实际花费最多的时间并集中精力在那里。

【讨论】:

  • 我理解,这是有道理的。但是,如果是这种情况,您能否举例说明我应该如何将 DateTime 作为数组处理?
  • 用示例更新了答案。但是我怀疑它会为您节省超过 1 毫秒的时间,我真的建议您获取配置文件并查看慢速部分的位置并专注于使它们更快。
  • 我再次更新它以使用秒表而不是 UtcNow。如果Stopwatch.IsHighResolution == falseit just uses UtcNow internally,但如果是真的,你会得到比 UtcNow 提供的更好的分辨率。
  • 我暂时无法验证它是否有帮助(由于个性化读/写方法的性质,但当它有帮助时,如果有帮助,我会接受你的回答并将其发布为最有用的。同时,谢谢...我认为它会有所帮助。
  • foreach 循环抛出 System.IndexOutOfRangeException,这似乎发生在 pArray。我觉得原因是字符串数组 pArray 的初始创建(空字符串数组应该是什么样子?)。除此之外,它似乎比我的原始代码要快一些。
猜你喜欢
  • 2012-08-19
  • 1970-01-01
  • 2018-04-18
  • 1970-01-01
  • 2012-06-28
  • 1970-01-01
  • 2021-04-22
  • 2022-01-17
  • 1970-01-01
相关资源
最近更新 更多