【问题标题】:Timer strange behaviour定时器奇怪的行为
【发布时间】:2013-02-04 17:37:30
【问题描述】:

如果我在属性窗口中将其Enabled 属性设置为 true,那么我在表单中使用了一个 Windows.Forms.Timer,这是它唯一有效的时间。如果我将其禁用,则仅在需要时启用它,它不会打勾。

        private void btnRename_Click(object sender, EventArgs e)
        {
            timerUpdateProgress.Enabled = true;
            timerUpdateProgress.Start();
            pbProgress.Maximum = clbFiles.CheckedItems.Count;
            var renameTask = Task.Factory.StartNew(() => doRename(true, tbCurrentDirectory.Text, clbFiles.CheckedItems, rules));
            if(renameTask.Result.Count > 0)
            {
                timerUpdateProgress.Enabled = false;
                new ExceptionsWindow(renameTask.Result).ShowDialog();
            }
            timerUpdateProgress.Enabled = false;
            loadFiles(tbCurrentDirectory.Text);
        }

        private void timerUpdateProgress_Tick(object sender, EventArgs e)
        {
            pbProgress.Value = progress; //I have a breakpoint on this line
        }

我要做的就是用进度条显示操作的进度。启用和启动计时器什么都不做,滴答声永远不会发生。为什么会这样?

更新:在启用和启动计时器后添加 2000 毫秒的睡眠后单步执行代码显示它仍然没有计时(我在计时处理程序中有一个断点)。

更多说明:在属性窗口中启用计时器时,总是会调用刻度处理程序,而无需调用Start()。只需启用计时器,我的断点就会一直触发。我还应该注意,我使用的是 .NET 4。

【问题讨论】:

  • 禁用/启用的原因是什么。为什么不在需要时停止/启动?
  • progress 中的值是多少??更新了吗?
  • 您似乎没有给计时器太多时间来打勾。您使用的间隔是多少?在您上面的代码中,计时器将运行的唯一时间是大约 4-5 行代码,这可能是几毫秒。
  • @DavidLloydBrookes 他们做同样的事情:msdn.microsoft.com/en-us/library/…
  • @RobinMaben 是的,它正在更新。 @onemancat doRename 方法是一个循环,所以它应该有一些时间去做,特别是因为它涉及到 IO。即便如此,我尝试在其中添加一个Thread.Sleep() 以在启用和启动它之后给它时间,但它仍然不起作用。

标签: c# timer


【解决方案1】:

编辑: 从 cmets 得到一个想法后 - 看来你 根本不需要计时器

您可以在progress 的值更新时更新进度条Value

这样从 0 到 100% 的过渡也可能看起来更顺畅。


根据我的说法,您需要禁用计时器。

随便用

timer.Stop();

然后在需要时timer.Start()

此外,如果您禁用了计时器进度,那么您还必须这样做

timerUpdateProgress.Enabled = true

【讨论】:

  • 终于,取得了一些进展! (请原谅双关语)我在属性中启用了计时器,然后在InitializeComponents() 之后在我的表单构造函数中使用了timerUpdateProgess.Stop()。然后当我单击开始操作的按钮时,我使用timerUpdateProgress.Start(),然后当操作完成时,我再次停止它。这取得了一些成功,但看起来操作仍在计时器计时完成之前完成。
  • 如果操作(有时)在计时器滴答之前完成,那么您还需要更新进度条,而不仅仅是在计时器滴答事件上。我根本不会使用计时器:而是在代码更新progress 的地方更新栏(看起来像一个类字段)。应该让事情变得更简单。
  • 当然你不能在非 UI 线程上更新进度条,我认为它是由 Task.Factory.StartNew 创建的。如果工作线程控制进度更新,则需要同步到 UI 线程(为此使用 Control.InvokeControl.BeginInvoke)。当我们进行线程同步时,您的代码是否同步读取/写入共享变量progress?如果没有,则存在竞争条件。
  • 这就是我最初的想法,但我遇到了从非 UI 线程访问 UI 的问题,这就是为什么我使用计时器来尝试解决这个问题。
  • BackgroundWorker 正是为这种情况而设计的。如果您不介意将您的逻辑绑定到 System.Windows.Forms 命名空间,这是最简单的选择 - msdn.microsoft.com/en-us/library/…
【解决方案2】:

“Task.Factory.StartNew”花了多长时间? (如果这是同步的)

如果上面的 lambda 表达式是异步的,我看看 renameTask.Result.Count 是否大于 0,progress bar = false...

【讨论】:

  • 我不知道我是否诚实。我不太了解 C# 线程,这是 SO 向我推荐的,它有效,所以我坚持使用它。我来自 Java,在那里创建线程就像实现接口一样简单。
猜你喜欢
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-11
  • 1970-01-01
相关资源
最近更新 更多