2017-02-28 29 views
-1

複数のstackoverflow、codeprojectソリューションを読むと、私の問題に統合できませんでした。wpfタイマーアプリケーション用の複数のディスパッチタイマー:複数のタイマーを同時に実行する

ウィンドウに読み込まれたusercontrolにデータグリッドがあります。 DataGridの各DataRowはタイマー設定を表します。

同様:

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

がボタンスタートをクリックし、行を選択するには、その行のタイマーを開始します。ディスパッチャのティックイベントでは、これまでに行ったグリッドを更新します。今私は、同じ時間に同じことをする別の(または2つの、または...)タイマーを起動しなければなりません。私はこれに固執しています。私が試したことを分かち合いましょう! 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; 
     })); 

    } 

btnStartClickEvent私はこのコードは、単一のタイマーのために知っています。 2行目をクリックしてタイマーを開始しようとすると、チックイベントでエラーが発生します。running rowはnullです。

このコードを保存して、複数のタイマーで動作させるにはどうすればいいですか?マルチスレッド化されている可能性があります。それを行うためのガイドは、非常に役立つでしょう。

答えて

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

このようにビジュアルツリーを更新することができないため、新しいSTAスレッドを開始する上記の部分は、このコンテキストでは不要で間違っています。 私は、以前の回答の1つでSTAスレッドを使用する正しい例を見つけることができます。https://stackoverflow.com/a/42473167/6996876

WPFのスレッドアフィニティの概念を理解してください。

UI作業をディスパッチャに委任する必要がある場合は、UpdateGrid()が必要です。

さらに、Tickイベントに引数を渡すすでにここで説明されていますhttps://stackoverflow.com/a/16380663/6996876 をあなたのケースでは、あなたはそれが代わりにイベントに渡されますように、現在のユニークrunningRowを変更することもできます。

+0

backgroundworker_doworkイベントに 'UpgradeGrid()'メソッドを追加しようとしました。バックグラウンドでDataGridをアップグレードします。しかし私はそのように試みたが、それは更新不可能になる。 –

+0

あなたは*ディスパッチャー*にすべてのUI作業*をしないので。私の答えをよく読んでください。 –

関連する問題