C#WPF/XAML从任意位置访问文本框/任意线程帮助

C#WPF/XAML从任意位置访问文本框/任意线程帮助,c#,wpf,textbox,backgroundworker,C#,Wpf,Textbox,Backgroundworker,我正在尝试从程序中的任何位置向文本框发帖,不管它在哪个线程中,或者是哪个对象拥有它等等 我试过下面的几件事,都不行 尝试1:tbLog在清理中不存在,另一个线程拥有它 namespace MyProgram { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); Cleanin

我正在尝试从程序中的任何位置向文本框发帖,不管它在哪个线程中,或者是哪个对象拥有它等等

我试过下面的几件事,都不行

尝试1:tbLog在清理中不存在,另一个线程拥有它

namespace MyProgram 
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Cleaning clng = new Cleaning(); 
        }

        public buttonStartTasks_Click(object sender, RoutedEventArgs e)
        {
            BackgroundWorker worker = new BackgroundWorker();

            worker.DoWork += delegate(object s, DoWorkEventArgs args)
            {
                Dispatcher.Invoke(new Action(delegate { tbLog.Text += "Starting to clean"; }));
                clng.cleanRoom(); 
            }

            worker.RunWorkerAsync();
        }
    }
}

namespace Tasks
{
    public class Cleaning
    {
        public void cleanRoom()
        {
            tbLog.Text += "Dusting...."; 
            Thread.Sleep(50000); //work sim
            tbLog.Text += "Sweeping...."; 
            Thread.Sleep(50000); //work sim
            tbLog.Text += "Hanging up clothes...."; 
            Thread.Sleep(50000); //work sim
            tbLog.Text += "Organize shelves...."; 
            Thread.Sleep(50000); //work sim
            tbLog.Text += "Remaining odds and ends...."; 
            Thread.Sleep(50000); //work sim
        }
    }
}
尝试2:我尝试将tbLog传递到清理中。我得到了这个错误“调用线程无法访问这个对象,因为另一个线程拥有它”。这是有道理的

namespace MyProgram 
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Cleaning clng = new Cleaning(tbLog); 
        }

        public buttonStartTasks_Click(object sender, RoutedEventArgs e)
        {
            BackgroundWorker worker = new BackgroundWorker();

            worker.DoWork += delegate(object s, DoWorkEventArgs args)
            {
                Dispatcher.Invoke(new Action(delegate { tbLog.Text += "!!! Starting to clean !!!"; }));
                clng.cleanRoom(); 
            }

            worker.RunWorkerAsync();
        }
    }
}

namespace Tasks
{
    public class Cleaning
    {

        private TextBox LOG { get; set; }

        public Cleaning(TextBox log)
        {
            this.LOG = log; 
        } 

        public void cleanRoom()
        {
            LOG.Text += "Dusting...."; 
            Thread.Sleep(50000); //work sim
            LOG.Text += "Sweeping...."; 
            Thread.Sleep(50000); //work sim
            LOG.Text += "Hanging up clothes...."; 
            Thread.Sleep(50000); //work sim
            LOG.Text += "Organize shelves...."; 
            Thread.Sleep(50000); //work sim
            LOG.Text += "Remaining odds and ends...."; 
            Thread.Sleep(50000); //work sim
        }
    }
}
尝试3:我试图在清理中使用Dispatcher,但出现编译错误,告诉我它不存在。所以现在我被卡住了。我不知道还能尝试什么。我在谷歌上搜索了很多,但总是归结为线程所有权错误

if (Dispatcher.Thread != Thread.CurrentThread)
{
    Dispatcher.Invoke(new Action(delegate { this.LOG.Text += "No clean for you!"; }));
}
else
{
    this.LOG.Text += "No clean for you!";
}
所有人的文本框:

<TextBox Name="tbLog"
    Height="200" 
    Width="200"
    HorizontalAlignment="Left" 
    VerticalAlignment="Top"  
    VerticalScrollBarVisibility="Visible" 
    IsReadOnly="True" />  


谢谢你的帮助

这是因为您不能仅对来自主UI线程以外的其他线程的控件执行操作。如果要执行此操作,必须使用
调度程序中的
Invoke
BeginInvoke


可以找到这方面的介绍,您还可以找到代码示例,这些示例将帮助您解决此问题。

我认为最好的方法是将textbox的文本属性绑定到依赖项属性,并从backgroundworker更新依赖项属性。要从线程更新文本框的值,您需要实现INotifyPropertyChanged。

我昨天刚刚在尝试从另一个线程增量加载列表框时遇到了这个问题。我将Dispatcher.Invoke()更改为Application.Current.Dispatcher.Invoke()。

您需要。

如果您想知道:使用System.Windows.Application,而不是System.Windows.Forms.Application