Como acessar diretamente o thread da interface do usuário do thread BackgroundWorker no WPF?

Estou criando um utilitário de backup no WPF e tenho umpergunta geral sobre segmentação:

No métodobackgroundWorker.DoWork (), a declaração Message2.Text = "..." dá o erro "O segmento de chamada não pode acessar esse objeto porque um segmento diferente é o proprietário dele.".

Não há nenhuma maneira para eu acessar diretamente o thread da interface do usuário no backgroundWorker.DoWork (), ou seja, alterar o texto em um TextBox XAML nesse ponto? Ou eu preciso armazenar todas as informações de exibição em umvariável internae, em seguida, exibi-lo embackgroundWorker.ProgressChanged ()como eu tive que fazer com, e. percentFinished?

XAML:

<Window x:Class="TestCopyFiles111.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1"  Height="350" Width="525">
    <DockPanel LastChildFill="True" HorizontalAlignment="Left" VerticalAlignment="Top"
                Margin="10">

        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top">
            <Button x:Name="Button_Start" 
                    HorizontalAlignment="Left"  
                    DockPanel.Dock="Top" 
                    Content="Start Copying" 
                    Click="Button_Start_Click" 
                    Height="25" 
                    Margin="0 0 5 0"
                    Width="200"/>
            <Button x:Name="Button_Cancel" 
                    HorizontalAlignment="Left"  
                    DockPanel.Dock="Top" 
                    Content="Cancel" 
                    Click="Button_Cancel_Click" 
                    Height="25" 
                    Width="200"/>
        </StackPanel>

        <ProgressBar x:Name="ProgressBar"
                     DockPanel.Dock="Top" 
                     HorizontalAlignment="Left"
                    Margin="0 10 0 0"
                    Height="23"
                     Width="405"
                     Minimum="0"
                     Maximum="100"
                     />

        <TextBlock DockPanel.Dock="Top" x:Name="Message" Margin="0 10 0 0"/>
        <TextBlock DockPanel.Dock="Top" x:Name="CurrentFileCopying" Margin="0 10 0 0"/>
        <TextBlock DockPanel.Dock="Top" x:Name="Message2" Margin="0 10 0 0"/>
    </DockPanel>
</Window>

Código por trás:

using System.Windows;
using System.ComponentModel;
using System.Threading;
using System.IO;
using System.Collections.Generic;
using System;

namespace TestCopyFiles111
{
    public partial class Window1 : Window
    {
        private BackgroundWorker backgroundWorker;

        float percentageFinished = 0;
        private int totalFilesToCopy = 0;
        int filesCopied = 0;

        string currentPathAndFileName;

        private List<CopyFileTask> copyFileTasks = new List<CopyFileTask>();
        private List<string> foldersToCreate = new List<string>();

        public Window1()
        {
            InitializeComponent();
            Button_Cancel.IsEnabled = false;
            Button_Start.IsEnabled = true;
            ProgressBar.Visibility = Visibility.Collapsed;

        }

        private void Button_Start_Click(object sender, RoutedEventArgs e)
        {
            Button_Cancel.IsEnabled = true;
            backgroundWorker = new BackgroundWorker();
            backgroundWorker.WorkerReportsProgress = true;
            backgroundWorker.WorkerSupportsCancellation = true;
            ProgressBar.Visibility = Visibility.Visible;

            AddFilesFromFolder(@"c:\test", @"C:\test2");

            Message.Text = "Preparing to copy...";

            MakeSureAllDirectoriesExist();

            CopyAllFiles();

        }


        void AddFilesFromFolder(string sourceFolder, string destFolder)
        {
            if (!Directory.Exists(destFolder))
                Directory.CreateDirectory(destFolder);
            string[] files = Directory.GetFiles(sourceFolder);
            foreach (string file in files)
            {
                string name = Path.GetFileName(file);
                string dest = Path.Combine(destFolder, name);
                copyFileTasks.Add(new CopyFileTask(file, dest));
                totalFilesToCopy++;
            }
            string[] folders = Directory.GetDirectories(sourceFolder);
            foreach (string folder in folders)
            {
                string name = Path.GetFileName(folder);
                string dest = Path.Combine(destFolder, name);
                foldersToCreate.Add(dest);
                AddFilesFromFolder(folder, dest);
            }
        }

        void MakeSureAllDirectoriesExist()
        {
            foreach (var folderToCreate in foldersToCreate)
            {
                if (!Directory.Exists(folderToCreate))
                    Directory.CreateDirectory(folderToCreate);
            }
        }

        void CopyAllFiles()
        {
            backgroundWorker = new BackgroundWorker();
            backgroundWorker.WorkerReportsProgress = true;
            backgroundWorker.WorkerSupportsCancellation = true;

            backgroundWorker.DoWork += (s, args) =>
            {
                filesCopied = 0;
                foreach (var copyFileTask in copyFileTasks)
                {
                    if (backgroundWorker.CancellationPending)
                    {
                        args.Cancel = true;
                        return;
                    }

                    DateTime sourceFileLastWriteTime = File.GetLastWriteTime(copyFileTask.SourceFile);
                    DateTime targetFileLastWriteTime = File.GetLastWriteTime(copyFileTask.TargetFile);

                    if (sourceFileLastWriteTime != targetFileLastWriteTime)
                    {
                        Message2.Text = "dates are not the same";
                    }
                    else
                    {
                        Message2.Text = "dates are the same";
                    }

                    if (!File.Exists(copyFileTask.TargetFile))
                        File.Copy(copyFileTask.SourceFile, copyFileTask.TargetFile);

                    currentPathAndFileName = copyFileTask.SourceFile;

                    UpdatePercentageFinished();
                    backgroundWorker.ReportProgress((int)percentageFinished);

                    filesCopied++;
                }

            };

            backgroundWorker.ProgressChanged += (s, args) =>
            {
                percentageFinished = args.ProgressPercentage;
                ProgressBar.Value = percentageFinished;
                Message.Text = percentageFinished + "% finished";
                CurrentFileCopying.Text = currentPathAndFileName;
            };

            backgroundWorker.RunWorkerCompleted += (s, args) =>
            {
                Button_Start.IsEnabled = true;
                Button_Cancel.IsEnabled = false;
                ProgressBar.Value = 0;
                UpdatePercentageFinished();
                CurrentFileCopying.Text = "";

                if (percentageFinished < 100)
                {
                    Message.Text = String.Format("cancelled at {0:0}% finished", percentageFinished);
                }
                else
                {
                    Message.Text = "All files copied.";
                }
            };

            backgroundWorker.RunWorkerAsync();
        }

        void UpdatePercentageFinished()
        {
            percentageFinished = (filesCopied / (float)totalFilesToCopy) * 100f;
        }


        class CopyFileTask
        {
            public string SourceFile { get; set; }
            public string TargetFile { get; set; }
            public CopyFileTask(string sourceFile, string targetFile)
            {
                SourceFile = sourceFile;
                TargetFile = targetFile;
            }
        }

        private void Button_Cancel_Click(object sender, RoutedEventArgs e)
        {
            backgroundWorker.CancelAsync();
        }

    }
}

questionAnswers(3)

yourAnswerToTheQuestion