我在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);
}
我在這裏沒有看到任何會導致提前退出的內容。但是你不顯示實際設置「IsHungry」的代碼。 –
我試圖避免發佈整個列表,但我可以,如果這將有所幫助。 –
所以你說的是測試*會運行幾秒/分鐘,但測試*輸出*只是說它運行得更少? –