Q:

Is it possible to Update UI from 2 background workers

I am working on a WPF application using C# and I wanted to implement a second background worker object. I already have 1 that works the way I want it to.
This first background worker updates a progress bar based on some operations.
I want the second to update a text block which displays a countdown timer.
First off, is this possible to do?
Currently, When the timer counts down and reaches zero, when the other thread tries to access the progress bar, it gives an error.

The calling thread cannot access this object because a different thread owns it.

Here is the code for my background workers:
In the main window method I initialize them.
        // Add the background worker events
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.ProgressChanged += worker_ProgressChanged;
        worker.WorkerReportsProgress = true;

        worker_timer.DoWork += worker_TrackTime;
        worker_timer.RunWorkerCompleted += worker_TimeCompleted;
        worker_timer.ProgressChanged += worker_timerProgressChanged;
        worker_timer.WorkerReportsProgress = true;

Here are the thread methods:
private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        // Run all background tasks here
        copyEverything(sourceFolder, targetFolder);
    }

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // Update UI once worker complete his work
        // Update the progress bar and progress percent text to the max value it can be
        copy_progressbar.Value = copy_progressbar.Maximum;
        copy_textblock.Text = copy_progressbar.Maximum + "%";

        worker.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
        worker.DoWork -= new DoWorkEventHandler(worker_DoWork);
    }

    void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // Update something here
        copy_progressbar.Value = e.ProgressPercentage;
        copy_textblock.Text = e.ProgressPercentage + "%";

        // Check if the progressbar has reached its maximum value, if so set the value to its max
        if (copy_progressbar.Value >= copy_progressbar.Maximum)
        {
            copy_progressbar.Value = copy_progressbar.Maximum;
            copy_textblock.Text = copy_progressbar.Maximum + "%";
        }
    }

    private void worker_TimeCompleted(object sender, RunWorkerCompletedEventArgs e)
    {

    }

    private void worker_TrackTime(object sender, DoWorkEventArgs e)
    {
        while (true)
        {
            Thread.Sleep(1000);
            elapsedTS = elapsedTS.Add(new TimeSpan(0, 0, 1));
            try
            {
                worker_timer.ReportProgress(1);
            }
            catch
            {
            }

            if (elapsedTS >= schedule.TS)
            {
                copyEverythingAsync(sourceFolder, targetFolder);
                schedule.updateSchedule(DateTime.Now, false);
                schedule.checkSchedule();
                checkScheduleTime();

                elapsedTS = TimeSpan.Zero;
            }
        }
    }

    private void worker_timerProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        time_left_textblock.Text = "" + schedule.TS.Subtract(elapsedTS).ToString(@"dd\.hh\:mm\:ss");
        //time_left_textblock.Text = "" + schedule.TS.Subtract(elapsedTS).ToString();
    }

The thread that tracks the timer does not have a completed method because I want it to continually run.
I can put more info if needed.

A:

You need to update the UI using UI thread.
   private void worker_timerProgressChanged(object sender, ProgressChangedEventArgs e)
    {
       Dispatcher.Invoke(() => 
       {
          time_left_textblock.Text = "" + schedule.TS.Subtract(elapsedTS).ToString(@"dd\.hh\:mm\:ss");
       });
    }

