多个计时器 WPF 应用程序,调用线程必须是 STA 错误

本文关键字:STA 错误 线程 调用 计时器 WPF 应用程序 | 更新日期: 2023-09-27 18:31:27

我的 WPF 应用程序涉及多个计时器。一切都适用于调度程序计时器,但延迟很大,并且经常发生冻结(例如 3 秒冻结,然后一次添加剩余的 3 秒)。

我的

问题是我不确定我必须如何重新设计我的应用程序来解决这个问题。以前从未使用过线程,它也是我的第一个真正的 WPF 应用程序。

我收到以下错误:调用线程必须是 STA,因为许多 UI 组件都需要这样做。

我通过用命名空间 System.timer 中的计时器替换我的调度程序计时器来获得此错误

带有调度程序计时器的旧代码:

timerW = new DispatcherTimer();
        timerW.Tick += new EventHandler(timerW_Tick);
        timerW.Interval = new TimeSpan(0, 0, 5000);
        timerW.Start();

带有计时器的新代码:

            timerW = new Timer();
            timerW.Elapsed += new ElapsedEventHandler(timerW_Tick);
            timerW.Interval = 5000; 
            timerW.Start();            

查询每 5 秒执行一次,以检索日期值。当满足某些条件时,按钮会动态创建。例如,如果日期在 3 分钟内保持不变,则会创建一个按钮。

动态创建按钮包含:

  • 数据库中的日期
  • 创建按钮时开始运行的计时器。此计时器仅在创建新按钮时停止,这会记录停机时间。
  • 停机的原因

这些按钮保存在可观察集合中,并使用依赖项属性,以便在发生更改时收到通知。它是一个带有多个文本块的自定义按钮,用于显示信息。

按钮部分是我的程序中所有交互的位置,界面的其余部分仅显示来自数据库的信息。按钮放置在自定义滑块中,例如带有左右导航按钮的控件。

简而言之,我的程序有 3 个不同的调度程序计时器。

  • 一个显示当前时间(hh:mm:ss格式)
  • 一个用于执行 sql 查询并每 5 秒检索一个日期值
  • 一个用于在动态自定义样式的 WPF 按钮内每秒更新停机时间计时器。我用秒表记录两者之间的停机时间。

所以看来我需要与踏板和/或背景工作者一起工作?

不知道我实际上是如何开始的,因为我已经有一段时间了。一些示例代码将非常受欢迎。

目录:

我使用计时器的原因如下:

  • 显示当前时间
  • 记录停机时间(实时,所以我实际上看到它按秒计数)
  • 每 5 秒执行一次的 SQL 查询。

编辑:

public void InitializeDispatcherTimerW()
    {
        TimerCallback callback = MyTimerCallBack;
        timerWegingen = new Timer(callback, null, 0, 5000);
        timerWegingen.Change(0, 5000);
    }
    private void MyTimerCallBack(object state)
    {
        DisplayWegingInfo();
        CaculateTimeBetweenWegingen();
    }

此致敬意杰克兹。

多个计时器 WPF 应用程序,调用线程必须是 STA 错误

System.Timers.Timer 似乎需要一个 STA 线程。STA 线程是 Windows 窗体的要求,但 WPF 显然不需要它。

System.Threading.Timer 是否满足您的需求?

下面是一个示例:

// firstTickInterval and interval are TimeSpans
TimerCallback callback = MyTimerCallback;
Timer timer = new Timer(callback, null, firstTickInterval, interval);
// timer is now running
// To stop the timer, do timer.Change(-1, -1);

回调函数如下所示:

void MyTimerCallback(object state)
{
    // This is not guaranteed to execute on the UI thread.
    // In this example, state will be null, since we passed null in the Timer constructor.
}

当计时器回调代码与 UI 元素交互时 您需要使用:

UIElement.Dispatcher.BeginInvoke(...);

更多信息: http://msdn.microsoft.com/en-us/magazine/cc163328.aspx