猿问

如何从另一个类中运行的另一个线程更新UI

如何从另一个类中运行的另一个线程更新UI

我目前正在编写我的第一个关于C#的程序,我对该语言非常陌生(迄今为止只用于C)。我做了很多研究,但所有的答案都太笼统了,我根本无法解决问题。

所以这里是我(非常常见)的问题:我有一个WPF应用程序,它从用户填充的几个文本框中获取输入,然后使用它来对它们进行大量计算。它们应该花费大约2-3分钟,所以我想更新进度条和文本块,告诉我当前的状态。此外,我需要存储用户的UI输入并将它们提供给线程,所以我有第三个类,我用它来创建一个对象,并希望将此对象传递给后台线程。显然我会在另一个线程中运行计算,因此UI不会冻结,但我不知道如何更新UI,因为所有计算方法都是另一个类的一部分。经过大量的研究后,我认为最好的方法是使用调度员和TPL,而不是背景工作者,

这里有一个非常简单的程序结构:

public partial class MainWindow : Window{
    public MainWindow()
    {
        Initialize Component();
    }

    private void startCalc(object sender, RoutedEventArgs e)
    {
        inputValues input = new inputValues();

        calcClass calculations = new calcClass();

        try
        {
             input.pota = Convert.ToDouble(aVar.Text);
             input.potb = Convert.ToDouble(bVar.Text);
             input.potc = Convert.ToDouble(cVar.Text);
             input.potd = Convert.ToDouble(dVar.Text);
             input.potf = Convert.ToDouble(fVar.Text);
             input.potA = Convert.ToDouble(AVar.Text);
             input.potB = Convert.ToDouble(BVar.Text);
             input.initStart = Convert.ToDouble(initStart.Text);
             input.initEnd = Convert.ToDouble(initEnd.Text);
             input.inita = Convert.ToDouble(inita.Text);
             input.initb = Convert.ToDouble(initb.Text);
             input.initc = Convert.ToDouble(initb.Text);
         }
         catch
         {
             MessageBox.Show("Some input values are not of the expected Type.", "Wrong Input", MessageBoxButton.OK, MessageBoxImage.Error);
         }
         Thread calcthread = new Thread(new ParameterizedThreadStart(calculations.testMethod);
         calcthread.Start(input);
    }public class inputValues{
    public double pota, potb, potc, potd, potf, potA, potB;
    public double initStart, initEnd, inita, initb, initc;}public class calcClass{

如果有人简单解释如何从testmethod内部更新UI,我将非常感激。由于我是C#和面向对象编程的新手,我很可能不会理解太复杂的答案,但我会尽我所能。

此外,如果某人有更好的想法(可能使用背景工作者或其他任何东西),我很乐意看到它。


暮色呼如
浏览 600回答 3
3回答

largeQ

你应该使用Dispatcher更新UI线程上的控件,并且正确地说,长时间运行的进程不应该在UI线程上运行。即使您在UI线程上异步运行长时间运行的进程,它仍然可能导致性能问题。应该注意的是,Dispatcher.CurrentDispatcher它将返回当前线程的调度程序,而不一定是UI线程。我认为你可以使用它Application.Current.Dispatcher来获取对UI线程的调度程序的引用,如果你可以使用它,但如果没有,你将不得不将UI调度程序传递给你的后台线程。通常我使用任务并行库进行线程操作而不是BackgroundWorker。我发现它更容易使用。例如,Task.Factory.StartNew(()&nbsp;=>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;SomeObject.RunLongProcess(someDataObject));哪里void&nbsp;RunLongProcess(SomeViewModel&nbsp;someDataObject){ &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<=&nbsp;1000;&nbsp;i++) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.Sleep(10); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Update&nbsp;every&nbsp;10&nbsp;executions &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(i&nbsp;%&nbsp;10&nbsp;==&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Send&nbsp;message&nbsp;to&nbsp;UI&nbsp;thread &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Application.Current.Dispatcher.BeginInvoke( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DispatcherPriority.Normal, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(Action)(()&nbsp;=>&nbsp;someDataObject.ProgressValue&nbsp;=&nbsp;(i&nbsp;/&nbsp;1000))); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}}
随时随地看视频慕课网APP
我要回答