2017-02-28 128 views
-1

讀取多個stackoverflow,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被發現爲空。

我在想我該如何保持這段代碼,並使其適用於多個定時器。可能是多線程。一個指導來做到這一點,將是非常有益的。

回答

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

由於無法以這種方式更新可視化樹,因此您在上下文中啓動新STA線程的所有上述部分都不需要和錯誤。 您可以在我之前的回答中找到一個使用STA線程的正確示例:https://stackoverflow.com/a/42473167/6996876

嘗試瞭解WPF中線程關聯的概念。

您只需要一個UpdateGrid(),您必須將UI工作委派給調度員。

此外,傳遞的參數來Tick事件已經說明這裏:https://stackoverflow.com/a/16380663/6996876 在你的情況,你可能要改變目前唯一runningRow,這樣它傳遞給事件來代替。

+0

我試圖加我'UpgradeGrid()'方法在backgroundworker_dowork事件。並在後臺升級數據網格。但是當我嘗試這種方式時,它變得不可更新。 –

+0

因爲你不這樣做*所有UI工作有*在* *調度。很好地閱讀我的答案。 – 2017-02-28 07:43:37