我在C#中实现了一个餐饮哲学家问题的解决方案(一段时间前,我不记得什么时候,什么地方不记得),最近我重新打开它,并添加了一些定时输出。当实际的测试运行需要很多很多秒时,测试似乎只运行几毫秒。事实上,我可以强迫它运行几分钟,尽管测试仍然显示不到500毫秒。
简而言之,我正在创建一个任务集合,让它们每个运行几秒钟(打开和关闭),在主执行中循环,直到它们完成,并写出开始和结束时间之间的差异。
下面是用于运行解决方案的NUnit单元测试:
[Test]
public void DoesEveryOneEat_WaitsForAllToFinish()
{
// arrange
var start = DateTime.Now;
// act
foreach (var philosopher in Thinkers)
{
philosopher.StartEating();
}
// wait
bool someoneIsHungry = true;
while (someoneIsHungry)
{
someoneIsHungry = false;
foreach (var philosopher in Thinkers)
{
if (!someoneIsHungry && philosopher.IsHungry)
someoneIsHungry = true;
}
}
Console.WriteLine(DateTime.Now.Subtract(start).Milliseconds);
// assert
Assert.AreEqual(false, Thinkers[0].IsHungry, "Philosopher 0 is hungry and ate for only " + Thinkers[0].AteForMillis + " milliseconds.");
Assert.AreEqual(false, Thinkers[1].IsHungry, "Philosopher 1 is hungry and ate for only " + Thinkers[1].AteForMillis + " milliseconds.");
Assert.AreEqual(false, Thinkers[2].IsHungry, "Philosopher 2 is hungry and ate for only " + Thinkers[2].AteForMillis + " milliseconds.");
Assert.AreEqual(false, Thinkers[3].IsHungry, "Philosopher 3 is hungry and ate for only " + Thinkers[3].AteForMillis + " milliseconds.");
Assert.AreEqual(false, Thinkers[4].IsHungry, "Philosopher 4 is hungry and ate for only " + Thinkers[4].AteForMillis + " milliseconds.");
}philosopher.StartEating();启动一个任务,直到一个令人满意的结果到达,然后退出:
public async void StartEating()
{
await Task.Factory.StartNew(Run);
}
public void Run()
{
while (_totalRunTime < MaxEatMillis)
{
if (Monitor.TryEnter(Left))
{
if (Monitor.TryEnter(Right))
{
Eat();
Monitor.Exit(Right);
}
Monitor.Exit(Left);
}
}
}虽然我欢迎对这段代码进行建设性的评论,但我的问题是:为什么单元测试控制台只输出582毫秒,而测试本身在9秒或更长时间内不容易完成?
(我推测这是因为实际单元测试代码运行所需的时间仅为582毫秒,但NUnit库不允许断言在测试启动的所有任务完成之前运行。然而,这在我的脑海中并不存在,就好像编写依赖于这个事实的代码会失败一样。)
完整清单:
public class ChopStick
{
public int Index { get; set; }
}
public class Philosopher
{
protected ChopStick Left { get; set; }
protected ChopStick Right { get; set; }
private int _totalRunTime = 0;
private readonly int MaxEatMillis = 3000;
private readonly int MaxRunMillis = 1000;
public Philosopher(ChopStick left, ChopStick right)
{
Left = left;
Right = right;
}
public async void StartEating()
{
await Task.Factory.StartNew(Run);
}
public void Run()
{
while (_totalRunTime < MaxEatMillis)
{
if (Monitor.TryEnter(Left))
{
if (Monitor.TryEnter(Right))
{
Eat();
Monitor.Exit(Right);
}
Monitor.Exit(Left);
}
}
}
private void Eat()
{
var eatTime = new Random().Next(1, MaxRunMillis);
Thread.Sleep(eatTime);
_totalRunTime += eatTime;
}
public bool IsHungry => _totalRunTime < MaxEatMillis;
public int AteForMillis => _totalRunTime;
}
[Test]
public void DoesEveryOneEat_WaitsForAllToFinish()
{
// arrange
var start = DateTime.Now;
Console.WriteLine(DateTime.Now.Subtract(start).Milliseconds);
// act
foreach (var philosopher in Thinkers)
{
philosopher.StartEating();
}
// wait
bool someoneIsHungry = true;
while (someoneIsHungry)
{
someoneIsHungry = false;
foreach (var philosopher in Thinkers)
{
if (!someoneIsHungry && philosopher.IsHungry)
someoneIsHungry = true;
}
}
Console.WriteLine(DateTime.Now.Subtract(start).Milliseconds);
// assert
Assert.AreEqual(false, Thinkers[0].IsHungry, "Philosopher 0 is hungry and ate for only " + Thinkers[0].AteForMillis + " milliseconds.");
Assert.AreEqual(false, Thinkers[1].IsHungry, "Philosopher 1 is hungry and ate for only " + Thinkers[1].AteForMillis + " milliseconds.");
Assert.AreEqual(false, Thinkers[2].IsHungry, "Philosopher 2 is hungry and ate for only " + Thinkers[2].AteForMillis + " milliseconds.");
Assert.AreEqual(false, Thinkers[3].IsHungry, "Philosopher 3 is hungry and ate for only " + Thinkers[3].AteForMillis + " milliseconds.");
Assert.AreEqual(false, Thinkers[4].IsHungry, "Philosopher 4 is hungry and ate for only " + Thinkers[4].AteForMillis + " milliseconds.");
Console.WriteLine(DateTime.Now.Subtract(start).Milliseconds);
}发布于 2017-06-01 13:52:37
在计时代码中,应该使用TotalMilliseconds而不是Milliseconds。
或者直接输出TimeSpan:
Console.WriteLine(DateTime.Now.Subtract(start));顺便提一下,Stopwatch通常用于计时,而不是DateTime.Now。
https://stackoverflow.com/questions/44301604
复制相似问题