WPF应用程序的多个计时器,调用线程必须是STA错误 [英] Multiple Timers WPF application, The calling thread must be STA Error

查看:102
本文介绍了WPF应用程序的多个计时器,调用线程必须是STA错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的WPF应用程序涉及几个计时器.一切都与DispatcherTimers一起使用,但延迟很大,并且经常发生冻结(例如冻结3秒,然后立即添加剩余的3秒).

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

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

我通过用命名空间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按钮中每秒更新一次停机计时器的功能.我使用秒表记录了两者之间的停机时间.

所以看来我需要和胎面和/或背景工作人员一起工作?

不知道我实际上是如何开始的,因为一段时间以来我的线索越来越少了.一些示例代码将是最受欢迎的.

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();
    }

最诚挚的问候, 杰克.

解决方案

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

My WPF application involves several timers. Everything works with DispatcherTimers but the delays are huge and freezes occur often (for example 3 sec freeze then the remaining 3 sec get added at once).

My problem is i am not sure how exactly i have to redesign my application to get around this problem. Never worked with threads before and its my first real WPF application as well.

I get the following error: The calling thread must be STA, because many UI components require this.

I got this error by replacing my Dispatcher timer by a Timer from the namespace System.Timers

Old code with dispatcher timer:

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

New code with Timer:

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

A query gets executed every 5 seconds to retreieve a date value. When certain conditions are met buttons get dynamically created. For example if the date remains the same for 3 min a button gets created.

Dynamic created button contains:

  • Date from the database
  • A timer that starts running when the buttons gets created. This timer only stops when a new button gets created, this records the downtime.
  • A reason for the downtime

The buttons get saved in a ObservableCollection and use Dependency Properties so they get notified when something changes. It is a custom button with several textblocks to display the information.

The button part is where all the interaction is at in my program, the rest of the interface just displays information fro the database. The buttons get placed in a custom made slider like control with left and right navigation buttons.

So in short my program has 3 different dispatcher timers.

  • One to display the current time (hh:mm:ss format)
  • One to execute a sql query and retrieve a date value every 5 sec
  • One to update the downtime timer every second inside a dynamically custom styled WPF button. I use a stopwatch to record the downtime in between.

So it seems i need to work with treads and/or backgroundworker?

Not sure how i actually begin with this since i am pretty clue less for some time now. Some example code would be most welcome.

Tldr:

I use timers for the following reasons:

  • Display the current time
  • Record downtime (real time, so i actually see it counting by the second)
  • A SQL query that gets executed every 5 seconds.

EDIT:

public void InitializeDispatcherTimerW()
    {
        TimerCallback callback = MyTimerCallBack;
        timerWegingen = new Timer(callback, null, 0, 5000);

        timerWegingen.Change(0, 5000);
    }

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

Best regards, Jackz.

解决方案

System.Timers.Timer seems to require an STA thread. An STA thread was a requirement for Windows Forms, but WPF apparently doesn't need it.

Does System.Threading.Timer meet your need?

Here is an example:

// 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);

The callback function would look like this:

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

这篇关于WPF应用程序的多个计时器,调用线程必须是STA错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆