【问题标题】:I am stuck in my while loop with elapsed time of a timer as condition我被困在我的while循环中,计时器的经过时间作为条件
【发布时间】:2021-05-15 01:51:34
【问题描述】:

我正在启动一个计时器,我希望该方法等到一段时间过去。我搜索了其他类似的问题,但找不到明确的答案。 为什么以下代码会冻结应用程序? 经过的时间从 0 开始,间隔为 1000(1 秒)

private void timer2_Tick(object sender, EventArgs e)
    {
        elapsedtime2++;
    }

//this is inside my method
timer2.Start();
while (elapsedtime2 < 3)
    {

    }
timer2.Stop();

【问题讨论】:

  • 您对elapsedTime2 的访问没有任何锁定,但它是由多个线程读取/写入的。运行时完全有权在elapsedtime2 &lt; 2 检查中删除elapsedtime2 的读取,这意味着您的循环变成了无限循环
  • (+1) 感谢您的评论。我正在努力学习,这是我一直在寻找的建设性批评。现在我知道出了什么问题。我将研究访问锁定以及何时/如何/为什么可以在运行时删除读取。
  • @canton7 能给个参考吗?我不知道运行时可以做这样的事情:remove the reads.
  • @rytisk 我手头没有,但编译器/运行时(甚至 CPU)允许重新排序读/写,这样的效果是许多语言的共同特征当前线程 看不到重新排序。这是例如为什么volatile 存在于 C 中。在 .NET 中,是 JIT 执行此操作,尽管不如其他一些语言那么多。
  • @rytisk:例如查看这个答案:stackoverflow.com/a/41634395/8248570 引用:“C# 编译器和 CLR 抖动允许进行大量优化,假设当前线程是唯一运行的线程。”

标签: c# while-loop timer


【解决方案1】:

您可以使用事件来获得所需的行为:

private int elapsedtime2 = 0;
private ManualResetEventSlim mre = new ManualResetEventSlim();

private void timer2_Tick(object sender, EventArgs e)
    {
        elapsedtime2++;
        if(elapsedtime2 >= 3)
        {
            mre.Set();
        }
    }

如果您的经过时间变量具有预期值,则可以设置事件。

mre.Reset();
timer2.Start();
mre.Wait();
timer2.Stop();

在启动计时器之前,取消设置事件。启动计时器后,等待事件设置完毕。

【讨论】:

  • 感谢您的回答。了解新的“工具”总是很棒的。我正在调查这些
【解决方案2】:

暂停执行一秒钟的最简单方法是:

Thread.Sleep(1000);

如果您熟悉 async/await,则等效的 async 是:

await Task.Delay(1000);

【讨论】:

  • Thread.Sleep() 这很好用。这种方法有什么限制吗?任何情况下我都不应该使用这些。
  • 这是其他问题的正常表现,但它本身并没有什么问题。当然,您的线程在此期间会变得无响应,因此,例如,如果它是 UI 线程,您的 UI 将会冻结
  • 我会在之前提到Task.Delay 而不是Thread.Sleep,因为如果编写 UI 可能更适合,就像这里的情况一样。
  • @JonasH 我没有看到有人提到这是一个 UI 应用程序?如果 OP 没有对 async/await 进行适当的介绍,那么将其扔给他们将无济于事。因为他们不知道 Thread.Sleep 我假设他们可能不熟悉 async/await
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-20
  • 2021-01-29
  • 2021-11-25
  • 2020-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多