将调度计时器更改为其他计时器以解决性能问题.无法更新 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# 类中编写的。
此致敬意杰克兹
当我运行我的代码示例时,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);
}