简体   繁体   English

从后台线程和线程中的线程更新UI

[英]Updating UI from a background Thread and thread within a Thread

I have following Application Structure: 我有以下应用程序结构:

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

From both of these threads Thread1 and Thread2 classes I want to update the TextBlock which is in the MainWindow . 从这两个Thread1 Thread2Thread2类中,我想更新MainWindowTextBlock

I have seen following solutions, and don't find this condition covered in this questions, also i am beginner and find it way difficult to understand. 我已经看到了以下解决方案,但没有发现此问题中涉及的这种情况,我还是新手,很难理解。

I can use solutions provided in the above questions for Thread1 but what about updating UI from Thread2 . 我可以将上述问题中提供的解决方案用于Thread1但如何从Thread2更新UI Thread2
I am using .NET framework 4.5. 我正在使用.NET Framework 4.5。
What is the best way of doing it. 最好的方法是什么。

…thread within a thread… …一个线程中的一个线程…

It appears that you have some misconceptions about what threads are. 似乎您对什么是线程有一些误解。 Let's look at these: 让我们看看这些:

  • Threads are not executed "within" one another. 线程不会彼此“内”执行。 They are not nested. 它们不是嵌套的。 It is more accurate to think of threads as being executed "side-by-side". 将线程视为“并排”执行更为准确。

    It doesn't matter how and where you started the second thread. 无论如何以及在何处启动第二个线程都无关紧要。 It's simply a thread, just like your first thread, so when you want to update the UI from within one of these (non-UI) threads, you do exactly the same thing in both cases: schedule your UI update code on the UI thread, which is done in WPF via the Dispatcher.Invoke or Dispatcher.InvokeAsync methods. 它只是一个线程,就像您的第一个线程一样,因此,当您想从这些(非UI)线程中的一个更新UI时,在两种情况下您都做同样的事情:在UI线程上安排UI更新代码,这是通过WPF中的Dispatcher.InvokeDispatcher.InvokeAsync方法完成的。

     myTextBlock.Dispatcher.Invoke(() => { … /* update myTextBlock here */ }); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // this will be scheduled on the correct (UI) thread 

    See also: How do I get the UI thread Dispatcher? 另请参阅: 如何获取UI线程分派器?

  • Threads are not the same as your Thread1 and Thread2 objects. 线程是不一样的你Thread1Thread2的对象。 Think of a thread as representing an execution path through your code; 将线程视为代表代码中的执行路径; or a method that is executed on its own, if you prefer. 或根据需要自行执行的方法。 A thread has an entry point (a method, represented by a ThreadStart delegate), which is where its execution starts, and the thread terminates when it reaches the end of that thread. 线程具有入口点(方法,由ThreadStart委托表示),该入口是其执行开始的位置,并且线程在到达该线程的结尾时终止。

     class Thread1 { … void doSomthing() { … Thread2 thread2 = new Thread2(); new Thread(new ThreadStart(thread2.doSomthing)).Start(); } } 

    Even though you named your classes Thread1 and Thread2 , that does not make them threads. 即使你命名你的类Thread1Thread2 ,这并不能让他们线程。 They are regular .NET classes that happen to contain the methods used as your threads' entry points. 它们是常规的.NET类,碰巧包含用作线程入口点的方法。 Threads are represented only by the Thread class (and take note that your classes do not, and could not, inherit from Thread ). 线程仅由Thread类表示(请注意,您的类不能也不可以从Thread继承)。 And again, it doesn't matter where you happen to .Start() them; 再次,没关系你在哪里发生.Start()他们。 they are independent from one another. 他们彼此独立。

  • When you have something like this: 当你有这样的事情:

     class A { … } class B { void Foo() { var a = new A(); … } 

    B only takes a part in where and when an instance of A gets created , but it doesn't determine "where" A is . B只需要在这样的情况:当一个部分A 被创建 ,但它并不确定“其中” A (Classes do not really have a location, anyway.) So it is wrong to say that " A is within B ". (无论如何,类实际上都没有位置。)所以说“ AB内”是错误的。 (The type A is referred to by a method of B , and a refers to an object instance that got created during the execution of an instance method of B , but it is still completely independent from B .) (类型A通过的方法称为 B ,和a指得到的一个实例方法的执行期间创建的对象实例B ,但它仍然是从完全独立的B )。


Update: Concerning your added question below about how to make myTextBlock known to your threads, there are two solutions: 更新:关于您在下面添加的有关如何使myTextBlock知道myTextBlock问题,有两种解决方案:

  1. Either move both doSomthing methods into the MainWindow class (and give them unique names). 可以将两个doSomthing方法都doSomthing MainWindow类中(并doSomthing赋予唯一的名称)。

  2. Pass myTextBlock to your Thread1 and Thread2 objects: 通过myTextBlockThread1Thread2的对象:

     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); // <-- … } } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM