简体   繁体   English

系统线程计时器

[英]System.Threading Timer

I am having problems converting my DispatcherTimer syntax to the Thread Timer. 我在将DispatcherTimer语法转换为线程计时器时遇到问题。 When i run my application suddenly it shuts down without any error. 当我突然运行我的应用程序时,它关闭,没有任何错误。

Basically i want the timer to execute 2 methods every 5 seconds. 基本上我希望计时器每5秒执行2个方法。

EDIT: The 2 methods are updating the UI. 编辑:2方法正在更新UI。 I am trying to attempt to get rid of the DispatcherTimer because i have to much freezes and delays in the UI display. 我试图摆脱DispatcherTimer,因为我不得不冻结和延迟UI显示。

Dispatcher timer code: 调度程序计时器代码:

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



 private void timerW_Tick(object sender, EventArgs e)
        {
            DisplayWegingInfo();
            CaculateTimen();
        }

Code for the System.Threading Timer: System.Threading计时器的代码:

public void InitializeDispatcherTimerW()
    {
        TimerCallback callback = MyTimerCallBack;
        timerW = new Timer(callback);

        timerW.Change(0, 5000);
    }

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

Thanks. 谢谢。

The problem most likely is that you are updating your UI in the methods in your timer callback. 问题很可能是您正在更新计时器回调中的方法中的UI。 This is only possible from the UI thread and the timer runs in a background thread. 这仅在UI线程中是可行的,并且计时器在后台线程中运行。

I suggest you stick with the DispatcherTimer . 我建议您坚持使用DispatcherTimer

An alternate solution would be to split the code up a bit: Extract the work intensive code into other methods and run them in a background thread and update the UI afterwards from the UI thread. 另一种解决方案是将代码分成几部分:将需要大量工作的代码提取到其他方法中,并在后台线程中运行它们,然后从UI线程中更新UI。

Something like this: 像这样:

private void MyTimerCallBack(object state)
{
    LongCalculationsThatDontNeedTheUI();
    _dispatcherUIThread.Invoke(new Action(UpdateUI));
}

Judging by the name DisplayWedgingInfo, I would guess this method updates the UI? 从名称DisplayWedgingInfo判断,我猜想此方法将更新UI? System.Threading.Timer executes on a thread that is different than the UI thread, so to be able to update the UI from that thread you would need to marshal those calls back to the Dispatcher thread using Dispatcher::[Begin]Invoke . System.Threading.Timer在与UI线程不同的线程上执行,因此要从该线程更新UI,您需要使用Dispatcher::[Begin]Invoke将这些调用编组回Dispatcher线程。

So you can leave whatever expensive work that doesn't touch UI elements as is, but for the UI manipulation you would simply do: 因此,您可以保留所有不会影响UI元素的昂贵工作,但是对于UI操作,您只需执行以下操作:

string someValue = this.SomeExpensiveOperation();

this.Dispatcher.BeginInvoke(
    DispatcherPriority.Background,
    new Action(() => 
   { 
          this.myControl.Text = someValue; 
   }));

I should point out that there will be some interruption to any UI interaction/rendering that might be going on when the invocation does occur. 我应该指出,调用确实发生时,任何可能正在进行的UI交互/渲染都会有些中断。 This is unavoidable as the execution will happen on the main thread. 这是不可避免的,因为执行将在主线程上进行。 By using DispatcherPriority.Background you at least schedule the update with a priority that keeps it lower than any input that the user might be providing at the time. 通过使用DispatcherPriority.Background您至少可以安排更新的优先级,使其优先级低于用户当时可能提供的任何输入。 However, don't expect to be able to make a massive update to the UI without any penalty. 但是,不要指望能够对UI进行大规模更新而不会带来任何损失。 If you need to do this it's best to queue up multiple invocations with Background priority so that they can happen with higher priority stuff like input in between if necessary. 如果您需要执行此操作,最好将具有“ Background优先级的多个调用排队,以使它们可以与更高优先级的东西一起发生,例如在必要时在它们之间进行输入。

I think you need to separate your data retrieval/calculation from your data display . 我认为您需要将数据检索/计算数据显示区分开

As Daniel points out, any GUI updating needs to be done on the Dispatcher thread, so the easiest way is to use DispatcherTimer . 正如Daniel指出的,任何GUI更新都需要在Dispatcher线程上完成,因此最简单的方法是使用DispatcherTimer

However, using DispatcherTimer means that everything in your timer callback gets done in the GUI thread. 但是,使用DispatcherTimer意味着计时器回调中的所有操作都在GUI线程中完成。 This is not good if you have any operations that take an appreciable amount of time. 如果您执行任何需要花费大量时间的操作,那将是不好的。 The GUI will stutter and lock up as you have found. 如您所见,GUI将结结巴巴并锁定。

You need to work out what is taking the time. 您需要弄清楚所花费的时间。 From your other question I would guess that it is the SQL retrieval. 从您的另一个问题,我想这是SQL检索。 In this case you would be better doing the actual retrieval on a separate thread (by using System.Threading.Timer ) and once you have the result, update the display by using Dispatcher.BeginInvoke() to marshal to the GUI thread. 在这种情况下,您最好在单独的线程上进行实际检索 (通过使用System.Threading.Timer ),一旦获得结果,就可以使用Dispatcher.BeginInvoke()编组到GUI线程来更新显示

I would check for 2 things: 1. As some others have said, make sure that if you are updating the UI, that you are Invoking back to the dispatcher -- you can only update the UI from the UI thread. 我将检查两件事:1.正如其他人所说,请确保如果要更新UI,则要调用回调度程序-您只能从UI线程更新UI。 Even if you are using databinding -- if a timer thread updates a value that is databound to the UI, that "counts" as the wrong thread touching the UI. 即使您正在使用数据绑定-如果计时器线程更新了绑定到UI的值,该“计数”为触摸UI的错误线程。

  1. Always protect your timeer callback with a try..catch block. 始终使用try..catch块保护计时器回调。 .Net's default behavior for unhandled exceptions is to terminate the process. .Net对于未处理异常的默认行为是终止进程。 I've seen lots of "just quit", where the real culprit was no exception handling on a timer thread, or a worker thread. 我见过很多“只是退出”,真正的罪魁祸首是计时器线程或辅助线程上没有异常处理。 (in fact, WPF should be throwing an exception if you try to manipulate the UI from the wrong thread, so it could be that you are getting the exception, and then the program terminates because there is no handler) (实际上,如果您尝试从错误的线程操作UI,WPF应该会引发异常,因此可能是您正在获取异常,然后由于没有处理程序而导致程序终止)

Why not simply use a background thread to dispatch events? 为什么不简单地使用后台线程来调度事件呢?

  CancellationTokenSource cts = new CancellationTokenSource();
  Task.Factory.StartNew(() =>
     {
          while(!cts.IsCancellationRequested)
          {
               Thread.Sleep(5000);

               this.Dispatcher.BeginInvoke(new Action(() =>
                  {
                       DisplayWegingInfo();
                       CalculateTimen();
                  }), null);
          }
     });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM