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

时间:2012-04-16 13:35:04

标签: c# wpf multithreading

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

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

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

我通过命名空间System.Timers

中的Timer替换我的Dispatcher计时器而得到此错误

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

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

使用Timer的新代码:

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

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

动态创建按钮包含:

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

按钮保存在 ObservableCollection 中并使用依赖项属性,以便在发生更改时收到通知。它是一个自定义按钮,包含多个文本块以显示信息。

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

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

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

所以我似乎需要使用踏板和/或 backgroundworker

我不确定我是如何开始这样做的,因为我现在很少有线索了。一些示例代码将是最受欢迎的。

Tldr:

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

  • 显示当前时间
  • 记录停机时间(实时,所以我实际上看到它按秒计数)
  • 每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();
    }

祝你好运, Jackz。

2 个答案:

答案 0 :(得分:1)

System.Timers.Timer似乎需要一个STA线程。 STA线程是Windows Forms的要求,但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.
}

答案 1 :(得分:0)

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

UIElement.Dispatcher.BeginInvoke(...);

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