我有以下应用程序结构:
public partial class MainWindow : Window
{
// Methos to update the TextBlock
public void updateTextBlock(string txt)
{
this.myTextBlock.Text += txt;
}
private void startThreadBtn_Click(object sender, RoutedEventArgs e)
{
// Start Thread1 here
Thread1 thread1 = new Thread1();
new Thread(new ThreadStart(thread1.doSomthing)).Start();
}
}
class Thread1
{
public void doSomthing()
{
// ------------------------------
// Update myTextBlock from here
// ------------------------------
// Thread2 starts here
Thread2 thread2 = new Thread2();
new Thread(new ThreadStart(thread2.doSomthing)).Start();
}
}
class Thread2
{
public void doSomthing()
{
// ------------------------------
// Update myTextBlock from here
// ------------------------------
}
}
从这两个线程Thread1
和Thread2
类中,我想要更新TextBlock
中的MainWindow
。
我已经看到了以下解决方案,并且在这些问题中没有找到这个条件,我也是初学者并且发现它很难理解。
我可以针对Thread1
使用上述问题中提供的解决方案,但是如何从Thread2
更新用户界面。
我正在使用.NET framework 4.5
这样做的最佳方式是什么。
答案 0 :(得分:3)
...线程内的线程......
您似乎对线程有什么误解。让我们来看看这些:
线程未执行"在"另一个。它们不是嵌套的。将线程视为正在执行"并排"更准确。
启动第二个帖子的方式和位置并不重要。它只是一个线程,就像你的第一个线程一样,所以当你想从其中一个(非UI)线程中更新UI时,你在两种情况下都做同样的事情:安排你的UI更新代码在UI线程上,通过Dispatcher.Invoke
或Dispatcher.InvokeAsync
方法在WPF中完成。
myTextBlock.Dispatcher.Invoke(() => { … /* update myTextBlock here */ });
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// this will be scheduled on the correct (UI) thread
主题与您的Thread1
和Thread2
对象不同。将线程视为代表执行代码的执行路径;或者,如果您愿意,可以单独执行的方法。一个线程有一个入口点(一个方法,由ThreadStart
委托表示),它是执行开始的地方,线程在到达该线程的末尾时终止。
class Thread1
{
… void doSomthing()
{
…
Thread2 thread2 = new Thread2();
new Thread(new ThreadStart(thread2.doSomthing)).Start();
}
}
即使您将类命名为Thread1
和Thread2
,也不会使它们成为线程。它们是常规的.NET类,恰好包含用作线程的方法。切入点。线程仅由Thread
类表示(请注意,您的类不会,也不能从Thread
继承)。再说一次,.Start()
他们碰到的地方并不重要;他们彼此独立。
当你有这样的事情时:
class A { … }
class B { void Foo() { var a = new A(); … }
B
只参与创建A
实例的位置和时间,但它并不确定"其中" A
是。 (无论如何,课程都没有真正的位置。)所以说#34; A
在B
"之内是错误的。 (类型A
是通过B
的方法引用,a
是指在执行<期间创建的对象实例< / em> B
的实例方法,但它仍完全独立于B
。)
更新:关于您在线程中了解如何使myTextBlock
知道的问题,有两个解决方案:
将doSomthing
个方法移动到MainWindow
类中(并赋予它们唯一的名称)。
将myTextBlock
传递给您的Thread1
和Thread2
个对象:
class Thread1
{
public Thread1(TextBlock textBlockToBeUpdated)
{
this.textBlock = textBlock;
}
private readonly TextBlock textBlock;
void doSomthing()
{
textBlock.Dispatcher.Invoke(() => { /* update textBlock here */ });
}
}
…
class MainWindow
{
… void startThreadBtn_Click(…)
{
Thread1 thread1 = new Thread1(myTextBlock); // <--
…
}
}