gpt4 book ai didi

c# - 从后台线程和线程内的线程更新 UI

转载 作者:行者123 更新时间:2023-11-30 20:46:55 24 4
gpt4 key购买 nike

我有以下应用程序结构:

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

我想从这两个线程 Thread1Thread2 类中更新 MainWindow 中的 TextBlock >。

我已经看到了以下解决方案,并没有发现这个问题涵盖了这种情况,而且我是初学者并且发现它很难理解。

我可以使用上述问题中为 Thread1 提供的解决方案,但是如何从 Thread2 更新 UI。
我正在使用 .NET Framework 4.5。
最好的方法是什么。

最佳答案

…thread within a thread…

看来您对什么是线程有一些误解。让我们看看这些:

  • 线程不在彼此“内部”执行。它们不是嵌套的。将线程视为“并行”执行更为准确。

    第二个线程的启动方式和位置并不重要。它只是一个线程,就像你的第一个线程,所以当你想从其中一个(非 UI)线程中更新 UI 时,你在两种情况下做完全相同的事情:在 UI 线程上安排你的 UI 更新代码,这是在 WPF 中通过 Dispatcher.InvokeDispatcher.InvokeAsync 方法完成的。

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

    另请参阅: How do I get the UI thread Dispatcher?

  • 线程与您的Thread1Thread2 对象不同。将线程视为代表代码的执行路径;或者如果您愿意,可以自行执行的方法。线程有一个入口点(一种方法,由 ThreadStart 委托(delegate)表示),这是它的执行开始的地方,线程在到达该线程的末尾时终止。

    class Thread1
    {
    … void doSomthing()
    {

    Thread2 thread2 = new Thread2();
    new Thread(new ThreadStart(thread2.doSomthing)).Start();
    }
    }

    即使您将类命名为 Thread1Thread2,也不会使它们成为线程。它们是常规的 .NET 类,恰好包含用作线程入口点的方法。线程仅由 Thread 类表示(请注意,您的类没有也不可能继承自 Thread)。再说一次,你在哪里碰巧 .Start() 它们并不重要;它们彼此独立。

  • 当你有这样的事情时:

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

    B 只参与 A 实例的创建位置和时间 ,但它不决定“位置” A 。 (无论如何,类并没有真正的位置。)所以说“A is within B”是错误的。 (类型 AB 的方法引用a 引用一个对象实例在执行 B 的实例方法时创建,但它仍然完全独立于 B。)


更新:关于您在下面添加的有关如何使线程知道 myTextBlock 的问题,有两种解决方案:

  1. 要么将两个 doSomthing 方法移动到 MainWindow 类中(并为它们指定唯一的名称)。

  2. myTextBlock 传递给您的 Thread1Thread2 对象:

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

    }
    }

关于c# - 从后台线程和线程内的线程更新 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26293506/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com