【问题标题】:Multiple Timers WPF application, The calling thread must be STA Error多个 Timers WPF 应用程序,调用线程必须是 STA 错误
【发布时间】:2012-04-16 13:35:04
【问题描述】:

我的 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();

带有计时器的新代码:

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

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

动态创建的按钮包含:

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

按钮保存在 ObservableCollection 中并使用依赖属性,以便在发生变化时得到通知。它是一个自定义按钮,带有几个文本块来显示信息。

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

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

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

所以看来我需要与 treads 和/或 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();
    }

最好的问候, 杰克兹。

【问题讨论】:

    标签: c# wpf multithreading


    【解决方案1】:

    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.
    }
    

    【讨论】:

    • 当我在使用线程计时器时尝试声明 tick 方法时,我似乎遇到了错误。
    • 没有 Tick 事件/方法。什么意思?
    • 我的意思是每隔 x 秒执行一次某个方法。我该如何使用这种计时器?
    • 你需要传递一个TimerCallback,这是一个返回void并接受单个对象参数的方法。
    • 您能否说明一下您的意思,我如何将这个计时器与我的旧调度程序代码一起使用?不完全确定在 void 方法中要做什么。谢谢。
    【解决方案2】:

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

    UIElement.Dispatcher.BeginInvoke(...);
    

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

    【讨论】:

    • 链接不再有效 -1。请在答案中提出解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-14
    • 2016-01-05
    相关资源
    最近更新 更多