首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么运行时间这么短?

为什么运行时间这么短?
EN

Stack Overflow用户
提问于 2017-06-01 07:49:45
回答 1查看 42关注 0票数 0

我在C#中实现了一个餐饮哲学家问题的解决方案(一段时间前,我不记得什么时候,什么地方不记得),最近我重新打开它,并添加了一些定时输出。当实际的测试运行需要很多很多秒时,测试似乎只运行几毫秒。事实上,我可以强迫它运行几分钟,尽管测试仍然显示不到500毫秒。

简而言之,我正在创建一个任务集合,让它们每个运行几秒钟(打开和关闭),在主执行中循环,直到它们完成,并写出开始和结束时间之间的差异。

下面是用于运行解决方案的NUnit单元测试:

代码语言:javascript
复制
[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();启动一个任务,直到一个令人满意的结果到达,然后退出:

代码语言:javascript
复制
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库不允许断言在测试启动的所有任务完成之前运行。然而,这在我的脑海中并不存在,就好像编写依赖于这个事实的代码会失败一样。)

完整清单:

代码语言:javascript
复制
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);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-06-01 13:52:37

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

或者直接输出TimeSpan

代码语言:javascript
复制
Console.WriteLine(DateTime.Now.Subtract(start));

顺便提一下,Stopwatch通常用于计时,而不是DateTime.Now

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44301604

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档