wpf用于定时器应用程序的多个调度定时器:精确运行多个定时器

问题描述:

读取多个*,codeproject解决方案,无法集成到我的问题。wpf用于定时器应用程序的多个调度定时器:精确运行多个定时器

在装载在窗口中的usercontrol中有一个datagrid。 DataGrid中的每个DataRow表示一个计时器设置。

像:

timer name : Test 1 , Timer : 1h 3m 
timer name : Test 2 , Timer : 2h 2m 
timer name : Test 3 , Timer : 3h 1m 

选择一行,点击按钮启动,启动该行的计时器。与调度员滴答事件,它更新我已完成的网格,直到此。现在我必须启动另一个(或两个或...)计时器,它将同时执行相同的操作。我困在此。让我分享我所尝试的!

btnStartClickEvent在mainwindow.xaml.cs

if (btnStart.Content.ToString() == "Start") 
     { 
      if (_AUC == ActiveUserControl.Grid) 
      { 
       runningRow = (TaskGridData)_TG.dgEmployee.SelectedItem; 
       if (runningRow != null) 
       { 
        currentlyRunningID.Add(runningRow.ID); 
        btnStart.Content = "Stop"; 
        //worker.RunWorkerAsync(runningRow); 
        StartTimer(runningRow); 
       } 
      } 
     } 
     else if (btnStart.Content.ToString() == "Stop") 
     { 
      btnStart.Content = "Start"; 
      StopTimer(); 

     } 
private DateTime TimerStart { get; set; } 
    private void StartTimer(TaskGridData tgd) 
    { 
     dispatcherTimer = new DispatcherTimer(); 

     dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1, 0); 
     dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick); 
     TimerStart = DateTime.Now; 
     dispatcherTimer.Start(); 
     //worker.RunWorkerAsync(); 

     //string etime = DateTime.Now.Second.ToString(); 
    } 

    private void StopTimer() 
    { 
     dispatcherTimer.Stop(); 
    } 
private void dispatcherTimer_Tick(object sender, EventArgs e) 
    { 
     var currentValue = DateTime.Now - TimerStart; 
     runningRow.Duration = DurationValueToString(currentValue); 
     temp = (List<TaskGridData>)_TG.dgEmployee.ItemsSource; 
     foreach (TaskGridData item in temp) 
     { 
      if (item.ID == runningRow.ID) 
      { 
       item.Duration = DurationValueToString(DurationStringToVlaue(item.Duration) - DurationStringToVlaue(runningRow.Duration)); 
       break; 
      } 
     } 
     //_TG.dgEmployee.ItemsSource = null; 
     //_TG.dgEmployee.ItemsSource = temp; 
     Thread NewThreadforStartProcessAfterTraining = new Thread(() => UpdateGrid()); 
     NewThreadforStartProcessAfterTraining.IsBackground = true; 
     NewThreadforStartProcessAfterTraining.SetApartmentState(ApartmentState.STA); 
     NewThreadforStartProcessAfterTraining.Start(); 

    } 
    private void UpdateGrid() 
    { 
     this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => 
     { 
      _TG.dgEmployee.ItemsSource = null; 
      _TG.dgEmployee.ItemsSource = temp; 
     })); 

    } 

我知道这个代码是一个计时器。如果我点击第二行并尝试启动计时器,那么它在tick事件中会出错,running row被发现为空。

我在想我该如何保持这段代码,并使其适用于多个定时器。可能是多线程。一个指导来做到这一点,将是非常有益的。

Thread NewThreadforStartProcessAfterTraining = new Thread(() => UpdateGrid()); 
    NewThreadforStartProcessAfterTraining.IsBackground = true; 
    NewThreadforStartProcessAfterTraining.SetApartmentState(ApartmentState.STA); 
    NewThreadforStartProcessAfterTraining.Start(); 

由于无法以这种方式更新可视化树,因此您在上下文中启动新STA线程的所有上述部分都不需要和错误。 您可以在我之前的回答中找到一个使用STA线程的正确示例:https://*.com/a/42473167/6996876

尝试了解WPF中线程关联的概念。

您只需要一个UpdateGrid(),您必须将UI工作委派给调度员。

此外,传递的参数来Tick事件已经说明这里:https://*.com/a/16380663/6996876 在你的情况,你可能要改变目前唯一runningRow,这样它传递给事件来代替。

+0

我试图加我'UpgradeGrid()'方法在backgroundworker_dowork事件。并在后台升级数据网格。但是当我尝试这种方式时,它变得不可更新。 –

+0

因为你不这样做*所有UI工作有*在* *调度。很好地阅读我的答案。 – 2017-02-28 07:43:37