我正试图从我的程序中的任何地方发布到一个文本框,无论它在哪个线程或者拥有它的对象等等......
我在下面尝试了一些事情,一切都行不通。
尝试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传递给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:我尝试在清理中使用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:
<TextBox Name="tbLog"
Height="200"
Width="200"
HorizontalAlignment="Left"
VerticalAlignment="Top"
VerticalScrollBarVisibility="Visible"
IsReadOnly="True" />
感谢您的帮助!
答案 0 :(得分:4)
我昨天只是在试图从另一个线程逐步加载ListBox。我通过将Dispatcher.Invoke()更改为Application.Current.Dispatcher.Invoke()来实现它。
答案 1 :(得分:0)
这是因为您不能仅对主UI线程以外的其他线程执行控件操作。如果您想这样做,则必须使用Invoke
中的BeginInvoke
或Dispatcher
。
可以找到here的简介,您还可以找到有助于解决此问题的代码示例。
答案 2 :(得分:0)
我想说最好的方法是将文本框的text属性绑定到依赖项属性,并从backgroundworker更新依赖项属性。要从线程更新文本框的值,您需要实现INotifyPropertyChanged。
答案 3 :(得分:0)