【问题标题】:Multiple Windows.Forms.Timer, slow application多个 Windows.Forms.Timer,应用缓慢
【发布时间】:2017-05-16 10:29:04
【问题描述】:

我的问题是关于在 c# Forms 应用程序中具有多个 Windows.Forms.Timer 的性能。

例如,timerHora 有 1 秒的间隔,在标签中显示当前小时。

我没有任何异步方法,因此,当我运行应用程序时,我的 GUI 不会每秒刷新小时标签,我猜它与其他计时器在同一线程中运行,它等待其他功能完成,所以它有时每秒刷新一次,有时 2,3 或 4 秒。

那么...你能推荐我处理这个问题的最佳实践吗?

【问题讨论】:

  • 您可以尝试减少计时器的数量,如this answer 中所述。另外我建议查看System.Timers.Timer而不是System.Windows.Forms.Timer 可能会提供一些性能优势。
  • 谢谢,我会试试看,如果这个计时器不起作用,我想我会尝试线程
  • System.Timers.Timer 确实使用单独的线程进行回调。但是您仍然需要与 UI 同步才能更改 UI。听起来您在 UI 线程上做的工作比您应该做的要多得多。将 UI 事物与阻塞和计算分开,UI 将保持响应。

标签: c# winforms performance timer


【解决方案1】:

你可以试试

public partial class Form1 : Form
{
    Task _task;
    CancellationTokenSource _token;

    public Form1()
    {
        InitializeComponent();
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        _token = new CancellationTokenSource();
        _task = Task.Factory.StartNew(() => DoWork(), _token.Token);            
    }

    protected override void OnClosing(CancelEventArgs e)
    {
        _token.Cancel();
        Application.DoEvents();
        _task.Wait();
        base.OnClosing(e);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            _task.Dispose();
            _token.Dispose();
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    private void SetTime()
    {
        var dt = DateTime.Now;
        label1.Text = $"{dt.Hour}:{dt.Minute}:{dt.Second}";
    }

    private void DoWork()
    {
        while (!_token.IsCancellationRequested)
        {
            if (InvokeRequired)
                Invoke(new MethodInvoker(SetTime));
        }
    }
}

【讨论】:

  • 这很有帮助,我有一个问题,如果我想运行多个方法,而不仅仅是 SetTime,我需要创建多个任务吗? onload 方法也是?
  • 嗯,当然,您可以添加多个任务,并在每个任务中调用特定的方法。但是由于它们都将使用相同的共享资源(UI),调用请求将被排队,而不是立即执行所以我会坚持一个任务,并且可能在里面有几个方法调用。可能有一些逻辑来决定必须调用哪个
【解决方案2】:

问题可能是 timmers 事件变慢了。 定时器在主线程中执行,所以如果你的代码很慢,你会减慢所有的表单。

尝试做线程而不是 timmers

【讨论】:

  • 我需要为这些事件应用间隔,所以我想我还是需要计时器?还是我错了?谢谢^^
  • @Ferus7 通常,您会使用计时器在后台开始处理。不同的要求需要不同的方法——如果你只是更新 UI,那么除了使用 winforms 计时器之外,没有任何意义。如果您需要偶尔从数据库更新 UI,您通常会将数据库更新作为在计时器事件上启动的后台任务运行,并在它们准备好时将结果编组回 UI 线程 (@987654321 @ 在大多数情况下让这很容易)。
  • 试过这个@Luaan,谢谢,但我无法每秒刷新一次用户界面,其中有一些繁重的方法:S
  • @Ferus7 同样,不要在 UI 线程上执行繁重的方法。那是你真正的问题 - 计时器事件“稍后”执行的事实只是这个问题的一个症状。无论计时器如何,当执行繁重的方法时,应用程序的 UI 仍然没有响应,这无论如何都是糟糕的 UX。如果一个方法需要足够长的时间才能引起注意(20-200 毫秒是一个粗略的阈值,具体取决于具体情况),那么它不应该在 UI 线程上。
  • 好的@Luann,非常感谢,我会尽量优化它^^
猜你喜欢
  • 1970-01-01
  • 2011-11-28
  • 2010-09-20
  • 1970-01-01
  • 1970-01-01
  • 2013-04-03
  • 2014-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多