为什么这么短的时间?

时间:2017-06-01 07:49:46

标签: asynchronous async-await task nunit-3.0

我在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毫秒?< / p>

(我猜测这是因为实际单元测试代码运行所花费的时间仅为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);
}

1 个答案:

答案 0 :(得分:1)

在您的计时代码中,您应该使用TotalMilliseconds而不是Milliseconds

或直接输出TimeSpan

Console.WriteLine(DateTime.Now.Subtract(start));

作为旁注,Stopwatch通常用于时间而不是DateTime.Now