-1

Read multiple stackoverflow, codeproject solution, could not integrate to my problem.

Have a datagrid in a usercontrol which is loaded in a window. Each DataRow in the DataGrid represents a timer setting.

Like:

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

Selecting a row, clicking on the button Start, Starts the timer of that row. And with dispatcher tick event, it updates the grid I have done till this. Now I have to start another(or two or ...) timer which will do the same at the same time. I am stuck on this. Let me share what I have tried!

btnStartClickEvent in 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;
        }));

    }

I know this code is for single timer. If I click a 2nd row and try to start timer, then it gets error in tick event, running row is found null.

I am wondering how can I keep this code and make it work for multiple timer. May be multithreading. A guide to do that, will be very helpful.

Abdur Rahim
  • 3,975
  • 14
  • 44
  • 83

1 Answers1

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

All the above part where you start a new STA thread is unneeded and wrong in this context, since you can't update the visual tree in this way. You can find a correct example of using a STA thread in one of my previous answers: https://stackoverflow.com/a/42473167/6996876

Try to understand the concept of thread affinity in WPF.

You simply need an UpdateGrid() where you have to delegate UI work to the dispatcher.

Furthermore, passing an argument to the Tick event is already explained here: https://stackoverflow.com/a/16380663/6996876 In your case you may want to change the current unique runningRow so that it's passed to the event instead.

Community
  • 1
  • 1
  • I tried to add my `UpgradeGrid() ` method in the backgroundworker_dowork event. and upgrade the datagrid in background. but while i tried that way, it becomes not updatable. – Abdur Rahim Feb 28 '17 at 07:35
  • Because you don't do *all UI work* there in the *dispatcher*. Read my answer well. –  Feb 28 '17 at 07:43