C# WPF / XAML 从任何地方/任何线程访问 TextBox 帮助

发布于 2024-10-22 06:03:20 字数 3445 浏览 4 评论 0原文

我试图从程序中的任何位置发布到文本框,无论它位于哪个线程或哪个对象拥有它等等......

我已经尝试了下面的一些方法,但都不起作用。

尝试 1: tbLog 在 Cleaning 中不存在,并且另一个线程拥有它。

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 传递到 Cleaning 中。我收到此错误“调用线程无法访问此对象,因为不同的线程拥有它”。这是有道理的。

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: 我尝试在 Cleaning 中使用 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" />  

感谢您的帮助!

I'm trying to post to a text box from anywhere in my program, regardless of what thread it's in or what object owns it etc...

I've tried a few things below, all won't work.

Attempt 1: tbLog doesn't exist in Cleaning and another thread owns it.

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
        }
    }
}

Attempt 2: I tried to pass tbLog into Cleaning. I got this error "The calling thread cannot access this object because a different thread owns it". Which makes sense.

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
        }
    }
}

Attempt 3: I tried to use Dispatcher in Cleaning and got compile error telling me it doesn't exist. So now I'm stuck. I don't know what else to try. I googled a bunch, but it always comes down to the thread ownership error.

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!";
}

The TextBox for all:

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

Thanks for any help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

牵你的手,一向走下去 2024-10-29 06:03:20

昨天我只是在搞乱这个尝试从另一个线程增量加载列表框。我通过将 Dispatcher.Invoke() 更改为 Application.Current.Dispatcher.Invoke() 来使其工作。

I was just messing with this yesterday trying to incrementally load a ListBox from another thread. I got it to work by changing Dispatcher.Invoke() to Application.Current.Dispatcher.Invoke().

戒ㄋ 2024-10-29 06:03:20

这是因为您不能只对主 UI 线程以外的其他线程的控件执行操作。如果您想执行此操作,则必须使用 Dispatcher 中的 InvokeBeginInvoke

对此的介绍可以在此处找到,您还可以找到那里的代码示例将帮助您解决这个问题。

This is because you can't just perform actions on controls from other threads than the main UI thread. If you want to do this, you have to use Invoke or BeginInvoke from the Dispatcher.

A introduction to this can be found here, you will also find code examples there which will help you with this problem.

七秒鱼° 2024-10-29 06:03:20

我想说最好的方法是将文本框的文本属性绑定到依赖属性,并从后台工作者更新依赖属性。为了从线程更新文本框的值,您需要实现 INotifyPropertyChanged。

I'd say the best way would be to bind the text property of your textbox to a dependency property, and update the dependency property from your backgroundworker. For the text box's value to update from the thread, you'll need to implement INotifyPropertyChanged.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文