c# - 如何从后台工作线程更改 XAML 元素?

标签 c# multithreading backgroundworker

在下面的代码示例中,我想从我的BackgroundThread更改文本框前景文本的颜色,但它收到错误强>:

This thread cannot access this object since it is in another thread.

我必须在下面的代码中更改什么,以便后台工作线程可以更改文本框中的前景色?

答案:

谢谢安迪,这只是一个小疏忽,为了后代,这里是更正后的代码:

using System.Windows;
using System.ComponentModel;
using System.Threading;
using System.Windows.Media;

namespace TestBackgroundWorker7338
{
    public partial class Window1 : Window
    {
        private BackgroundWorker _worker;
        int _percentageFinished = 0;

        public Window1()
        {
            InitializeComponent();
            ButtonCancel.IsEnabled = false;
        }

        private void Button_Start(object sender, RoutedEventArgs e)
        {
            _worker = new BackgroundWorker();
            _worker.WorkerReportsProgress = true;
            _worker.WorkerSupportsCancellation = true;

            _worker.DoWork += (s, args) =>
            {
                BackgroundWorker worker = s as BackgroundWorker;
                int numberOfTasks = 300;
                for (int i = 1; i <= numberOfTasks; i++)
                {
                    if (worker.CancellationPending)
                    {
                        args.Cancel = true;
                        return;
                    }

                    Thread.Sleep(10);
                    float percentageDone = (i / (float)numberOfTasks) * 100f;
                    worker.ReportProgress((int)percentageDone);
                }
            };

            _worker.ProgressChanged += (s,args) =>
            {
                _percentageFinished = args.ProgressPercentage;
                ProgressBar.Value = _percentageFinished;
                Message.Text = _percentageFinished + "% finished";
                if (_percentageFinished < 500)
                {
                    Message.Text = "stopped at " + _percentageFinished + "%";
                }
                else
                {
                    Message.Text = "finished";
                }

                if (_percentageFinished >= 70)
                {
                    InputBox.Foreground = new SolidColorBrush(Colors.Red);
                }
                else if (_percentageFinished >= 40)
                {
                    InputBox.Foreground = new SolidColorBrush(Colors.Orange);
                }
                else if (_percentageFinished >= 10)
                {
                    InputBox.Foreground = new SolidColorBrush(Colors.Brown);
                }
                else
                {
                    InputBox.Foreground = new SolidColorBrush(Colors.Black);
                }

            };

            _worker.RunWorkerCompleted += (s,args) =>
            {
                ButtonStart.IsEnabled = true;
                ButtonCancel.IsEnabled = false;
                ProgressBar.Value = 0;
            };

            _worker.RunWorkerAsync();
            ButtonStart.IsEnabled = false;
            ButtonCancel.IsEnabled = true;

        }

        private void Button_Cancel(object sender, RoutedEventArgs e)
        {
            _worker.CancelAsync();
        }
    }
}

最佳答案

正如 Andy 所说,更改控件的属性必须发生在 UI 线程上。

WPF 提供了一个 Dispatcher 类,可以更轻松地将控件调用路由到适当的 UI 线程。 WPF 中的控件公开一个 Dispatcher 属性对象,以将调用分派(dispatch)到适当的 UI 线程。

您可以按如下方式使用它(我会在 Button_Start 方法中的 worker.ReportProgress((int)percentageDone); 行之后添加它):

// the Window class exposes a Dispatcher property, alternatively you could use
// InputBox.Dispatcher to the same effect
if (!Dispatcher.CheckAccess())
     {
        Dispatcher.Invoke(new Action(() => ChangeForegroundColor(percentageDone));
     }
     else
     {
        ChangeForegroundColor(percentageDone);
     }

...
private void ChangeForegroundColor(int percentageDone)
{
    if (percentageDone >= 90)
    {
        InputBox.Foreground = new SolidColorBrush(Colors.Red);
    }
    else if(percentageDone >=10)
    {
        InputBox.Foreground = new SolidColorBrush(Colors.Orange);
    }
}

关于c# - 如何从后台工作线程更改 XAML 元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1206077/

相关文章:

java - 使用 SwingWorker 从 map 中检索数据

c# - BackgroundWorker 在 VSTO 中不工作

c# - 等待这些 BackgroundWorker 中的任何一个完成

c# - 进程不适用于 Ubuntu 但适用于 Windows

c# - NAudio算法播放频率可以实时平滑变化的正弦波

c# - 如何在不在同一个新窗口中打开新窗口?

c# - WPF中BackgroundWorker线程如何直接访问UI线程?

c# - selenium 2.0如何在注册表中选择性别?

c++ - 从线程池调用时,boost 的 io_service 是否共享请求线程?

java - 如何根据数组中的类名在java中使用大量对象