存储值以不同的时间间隔发送到控制台
Stored values send to Console in different time intervals
I've figured out how to store Data from a .csv to a List<>.
我有两个列表:ListA
包含每个值的时间戳,ListB
包含值。
看起来像这样:
A (time [ms]) | B (value)
---------------------------
0,00 | 49,33
154,71 | 49,46
244,92 | 49,72
855,11 | 49,64
...
And so on (over 50.000 values)
我的实际问题是:
我想在(几乎)准确的时间使用 WriteLine(listA[i]);
将值发送到控制台,就像实际值的时间戳一样。
我想到了一个秒表,我将它与时间戳进行比较,以便在正确的时刻给出正确的值?
这可能吗?
更新#1:
这是我的代码。它有效(有点)。但是我不确定是否有更好的解决方案?
stopwatch.Start();
while(true)
{
for (int i = 0; i < 50000; i++)
{
if (Math.Abs(stopwatch.Elapsed.TotalMilliseconds - Convert.ToDouble(listA[i]) * 1000) < 10)
{
Console.WriteLine(listB[i]);
}
}
Thread.Sleep(5);
}
更新#2:
我正在尝试了解Mong Zhu @disclaimer 的解决方案。
我的目标是创建一个由计时器启动的方法(例如每 100 毫秒)。我已经有了解决这个问题的代码:时间戳和秒表有时不同步,它会跳过一些值。
这是我的方法(每 100 毫秒调用一次):
public double getvalue()
{
if (stopwatch.ElapsedMilliseconds > Convert.ToDouble(ListA[ListA.Count-1])*1000)
{
stopwatch.Stop();
}
else
{
for (var i = 0; i < ListA.Count; i++)
{
if (Math.Abs(stopwatch.ElapsedMilliseconds - Convert.ToDouble(ListA[i]) * 1000) < 5)
{
value = Convert.ToDouble(ListB[i]);
break;
}
}
}
return value;
}
如果您只有一个所需类型的列表而不是两个单独的列表,您的实施会容易得多。让我解释一下:
您使用所需的属性创建 class:
public class YourClass
{
public long TimeMS {get; set;}
public Double Value {get; set;}
}
然后你可以简单地创建一个List<YourClass>
List<YourClass> list = new List<YourClass>();
list.Add( new YourClass { TimeMS = 154.71, Value = 49.46 } );
那么迭代起来就容易多了:
foreach(YourClass c in list)
{
//DO ALL YOUR WORK
Console.WriteLine(c.TimeMS.ToString() + ": " + c.Value.ToString());
}
如果您想使用 StopWatch
,那么我会切换 for
和 while
循环。只有在超过时间间隔并将值写入控制台后,才迭代到下一个位置。这是一个示例程序:
void Main()
{
Stopwatch stopWatch = new Stopwatch();
List<int> ListA = new List<int>() { 0, 154, 244, 855 };
List<double> ListB = new List<double>() { 49.33, 49.46, 49.72, 49.64 };
stopWatch.Start();
for (int i = 0; i < ListA.Count; i++)
{
while (stopWatch.ElapsedMilliseconds < ListA[i] * 1000)
{
Thread.Sleep(5);
}
Console.WriteLine($"Value: {ListB[i]} TIME: {stopWatch.ElapsedMilliseconds}");
}
stopWatch.Stop();
Console.ReadKey();
}
您的代码中的问题:
1) for (int i = 0; i < 50000; i++)
如果您遍历集合,最好不要为 for 循环使用固定数字。集合的大小可能会发生变化,固定数量将导致越界异常或未处理的值。如果是 List
,则使用 Count
;如果是数组,则使用 Length
2) 在每次 while 迭代中,您都在遍历整个数组。如果您真的想按值打印,这是一个很大的开销。
免责声明。我的解决方案中的 while
循环称为忙等待。这并不是真正可取的,因为 CPU 被占用而实际上什么都不做。一个更好的解决方案是使用计时器:
System.Timers.Timer timer = new System.Timers.Timer();
// register the event which will be fired
timer.Elapsed += PrintValuesAtTime;
timer.Interval = 1; // an intervall of 0 is not allowed
timer.AutoReset = true; // repeated execution of the timer
timer.Start(); // start the timer
Console.ReadLine();
我会制作一个新列表,其中包含与 ListA
的所有时间戳差异,可以用作下一次打印的时间间隔。类似于:
List<int> ListAIntervals = new List<int>() { 0, 154-0, 244-154, 855-244 };
并且在 Elapsed
事件处理程序中,您可以处理打印逻辑。您需要一个外部计数器来遍历您的集合:
private void PrintValuesAtTime(object sender, EventArgs args)
{
System.Timers.Timer timer = sender as System.Timers.Timer;
// only print values if there are enough values
if (counter < ListAIntervals.Count && counter < ListB.Count)
{
Console.WriteLine($"Value: {ListB[counter]}");
// there needs to be enough intervals left to go one more time
if (counter < ListAIntervals.Count - 1 && counter < ListB.Count - 1)
{
counter++;
timer.Interval = ListAIntervals[counter] * 1000; // to make it in msec
}
else
{
// stop the timer
timer.AutoReset = false;
}
}
}
I've figured out how to store Data from a .csv to a List<>.
我有两个列表:ListA
包含每个值的时间戳,ListB
包含值。
看起来像这样:
A (time [ms]) | B (value)
---------------------------
0,00 | 49,33
154,71 | 49,46
244,92 | 49,72
855,11 | 49,64
...
And so on (over 50.000 values)
我的实际问题是:
我想在(几乎)准确的时间使用 WriteLine(listA[i]);
将值发送到控制台,就像实际值的时间戳一样。
我想到了一个秒表,我将它与时间戳进行比较,以便在正确的时刻给出正确的值?
这可能吗?
更新#1:
这是我的代码。它有效(有点)。但是我不确定是否有更好的解决方案?
stopwatch.Start();
while(true)
{
for (int i = 0; i < 50000; i++)
{
if (Math.Abs(stopwatch.Elapsed.TotalMilliseconds - Convert.ToDouble(listA[i]) * 1000) < 10)
{
Console.WriteLine(listB[i]);
}
}
Thread.Sleep(5);
}
更新#2:
我正在尝试了解Mong Zhu @disclaimer 的解决方案。 我的目标是创建一个由计时器启动的方法(例如每 100 毫秒)。我已经有了解决这个问题的代码:时间戳和秒表有时不同步,它会跳过一些值。
这是我的方法(每 100 毫秒调用一次):
public double getvalue()
{
if (stopwatch.ElapsedMilliseconds > Convert.ToDouble(ListA[ListA.Count-1])*1000)
{
stopwatch.Stop();
}
else
{
for (var i = 0; i < ListA.Count; i++)
{
if (Math.Abs(stopwatch.ElapsedMilliseconds - Convert.ToDouble(ListA[i]) * 1000) < 5)
{
value = Convert.ToDouble(ListB[i]);
break;
}
}
}
return value;
}
如果您只有一个所需类型的列表而不是两个单独的列表,您的实施会容易得多。让我解释一下:
您使用所需的属性创建 class:
public class YourClass
{
public long TimeMS {get; set;}
public Double Value {get; set;}
}
然后你可以简单地创建一个List<YourClass>
List<YourClass> list = new List<YourClass>();
list.Add( new YourClass { TimeMS = 154.71, Value = 49.46 } );
那么迭代起来就容易多了:
foreach(YourClass c in list)
{
//DO ALL YOUR WORK
Console.WriteLine(c.TimeMS.ToString() + ": " + c.Value.ToString());
}
如果您想使用 StopWatch
,那么我会切换 for
和 while
循环。只有在超过时间间隔并将值写入控制台后,才迭代到下一个位置。这是一个示例程序:
void Main()
{
Stopwatch stopWatch = new Stopwatch();
List<int> ListA = new List<int>() { 0, 154, 244, 855 };
List<double> ListB = new List<double>() { 49.33, 49.46, 49.72, 49.64 };
stopWatch.Start();
for (int i = 0; i < ListA.Count; i++)
{
while (stopWatch.ElapsedMilliseconds < ListA[i] * 1000)
{
Thread.Sleep(5);
}
Console.WriteLine($"Value: {ListB[i]} TIME: {stopWatch.ElapsedMilliseconds}");
}
stopWatch.Stop();
Console.ReadKey();
}
您的代码中的问题:
1) for (int i = 0; i < 50000; i++)
如果您遍历集合,最好不要为 for 循环使用固定数字。集合的大小可能会发生变化,固定数量将导致越界异常或未处理的值。如果是 List
,则使用 Count
;如果是数组,则使用 Length
2) 在每次 while 迭代中,您都在遍历整个数组。如果您真的想按值打印,这是一个很大的开销。
免责声明。我的解决方案中的 while
循环称为忙等待。这并不是真正可取的,因为 CPU 被占用而实际上什么都不做。一个更好的解决方案是使用计时器:
System.Timers.Timer timer = new System.Timers.Timer();
// register the event which will be fired
timer.Elapsed += PrintValuesAtTime;
timer.Interval = 1; // an intervall of 0 is not allowed
timer.AutoReset = true; // repeated execution of the timer
timer.Start(); // start the timer
Console.ReadLine();
我会制作一个新列表,其中包含与 ListA
的所有时间戳差异,可以用作下一次打印的时间间隔。类似于:
List<int> ListAIntervals = new List<int>() { 0, 154-0, 244-154, 855-244 };
并且在 Elapsed
事件处理程序中,您可以处理打印逻辑。您需要一个外部计数器来遍历您的集合:
private void PrintValuesAtTime(object sender, EventArgs args)
{
System.Timers.Timer timer = sender as System.Timers.Timer;
// only print values if there are enough values
if (counter < ListAIntervals.Count && counter < ListB.Count)
{
Console.WriteLine($"Value: {ListB[counter]}");
// there needs to be enough intervals left to go one more time
if (counter < ListAIntervals.Count - 1 && counter < ListB.Count - 1)
{
counter++;
timer.Interval = ListAIntervals[counter] * 1000; // to make it in msec
}
else
{
// stop the timer
timer.AutoReset = false;
}
}
}