将调度计时器更改为其他计时器以解决性能问题.无法更新 UI,程序关闭

本文关键字:计时器 更新 UI 程序 问题 性能 调度 其他 解决 | 更新日期: 2023-09-27 18:31:19

>编辑#1:我放置了工人。RunWorkerAsync() 在我的计时器循环中,我的应用程序不再关闭。虽然现在似乎什么都没有发生。

出于性能原因,我需要将调度程序计时器替换为在不同线程中运行的其他计时器。有很多延迟/冻结,因此调度程序计时器不再是一种选择。

我在实际更新我的 GUI 线程时遇到问题,我的应用程序似乎总是关闭而没有任何警告/错误。我主要尝试使用BackGroundWorkers来解决我的问题。当我启动应用程序时,一切都会导致我的应用程序关闭。

一些代码示例将非常适用。

旧代码调度程序代码:

    public void InitializeDispatcherTimerWeging()
    {
        timerWegingen = new DispatcherTimer();
        timerWegingen.Tick += new EventHandler(timerWegingen_Tick);
        timerWegingen.Interval = new TimeSpan(0, 0, Convert.ToInt16(minKorteStilstand));
        timerWegingen.Start();
    }
    private void timerWegingen_Tick(object sender, EventArgs e)
    {
        DisplayWegingInfo();
        CaculateTimeBetweenWegingen();
    }

每 5 秒应调用一次 DisplayWegingInfo() 和 Compute 方法。

GUI 更新发生在计算方法中。在那里,一个按钮被动态创建并添加到可观察的集合中。

按钮创建(简短版本):

    public void CreateRegistrationButton()
    {
        InitializeDispatcherTimerStilstand();
        RegistrationButton btn = new RegistrationButton(GlobalObservableCol.regBtns.Count.ToString());
        btn.RegistrationCount = GlobalObservableCol.regBtnCount;
        btn.Title = "btnRegistration" + GlobalObservableCol.regBtnCount;
        btn.BeginStilstand = btn.Time;
        GlobalObservableCol.regBtns.Add(btn);
        GlobalObservableCol.regBtnCount++;
        btn.DuurStilstand = String.Format("{0:D2}:{1:D2}:{2:D2}", 0, 0, 0);         
    }
使用线程计时器

的新代码,该计时器在不同的线程中运行,然后是 GUI

    public void InitializeDispatcherTimerWeging()
    {
        worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(Worker_DoWork);
        worker.RunWorkerAsync();
    }
    void Worker_DoWork(object sender, DoWorkEventArgs e)
    {
        TimerCallback callback = MyTimerCallBack;
        timerWegingen = new Timer(callback);
        timerWegingen.Change(0, 5000);
    }

    private void MyTimerCallBack(object state)
    {
        DisplayWegingInfo();
        CaculateTimeBetweenWegingen();
    }

I 计时器在单独的线程中运行,然后是 GUI 线程(调度程序计时器使用)。但是我似乎无法将此更新发送到 UI 线程本身,因此更新在 UI 中实际实现。

该按钮每隔 1 秒通过另一个计时器重新填充新值。"DuurStilstand"是一个依赖属性

    private void FillDuurStilstandRegistrationBtn()
    {
        TimeSpan tsSec = TimeSpan.FromSeconds(stopWatch.Elapsed.Seconds);
        TimeSpan tsMin = TimeSpan.FromMinutes(stopWatch.Elapsed.Minutes);
        TimeSpan tsHour = TimeSpan.FromMinutes(stopWatch.Elapsed.Hours);
        if (GlobalObservableCol.regBtns.Count >= 1
                    && GlobalObservableCol.regBtns[GlobalObservableCol.regBtns.Count - 1].StopWatchActive == true)
        {
            GlobalObservableCol.regBtns[GlobalObservableCol.regBtns.Count - 1].DuurStilstand =
                            String.Format("{0:D2}:{1:D2}:{2:D2}", tsHour.Hours, tsMin.Minutes, tsSec.Seconds);
        }
    }

我是否需要在上述方法中使用调度程序的调用?如果是这样,究竟如何?

初始化 BackGroundWorker 的 doWork 方法后不确定如何调用 ui 线程,我的应用程序在启动后立即关闭。我尝试过在几种方法中使用Dispatcher.BeginInvoke,但到目前为止都失败了。目前我不知道如何实现它。

上述所有代码都是在单独的 c# 类中编写的。

此致敬意杰克兹

将调度计时器更改为其他计时器以解决性能问题.无法更新 UI,程序关闭

当我运行我的代码示例时,DisplayWegingInfo() 在尝试访问 UI 组件时抛出异常。 我们需要从 Timer 线程调用 Invoke() 来更新 UI。 请参阅下面的 DisplayWegingInfo()。 注意:这假设 CaculateTimeBetweenWegingen() 不与 UI 交互。

   void Worker_DoWork(object sender, DoWorkEventArgs e)
    {
        TimerCallback callback = MyTimerCallBack;
        timerWegingen = new System.Threading.Timer(callback);
        timerWegingen.Change(0, 3000);
    }
    private void MyTimerCallBack(object state)
    {
        DisplayWegingInfo();
        CaculateTimeBetweenWegingen();
    }
    private void DisplayWegingInfo()
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new Action(DisplayWegingInfo));
            return;
        }
        // at this point, we are on the UI thread, and can update the GUI elements
        this.label1.Text = DateTime.Now.ToString();
    }
    private void CaculateTimeBetweenWegingen()
    {
        Thread.Sleep(1000);
    }