为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
哔哔one 2019-08-13 15:45:05
如何从另一个类中运行的另一个线程更新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#和面向对象编程的新手,我很可能不会理解太复杂的答案,但我会尽我所能。此外,如果某人有更好的想法(可能使用背景工作者或其他任何东西),我很乐意看到它。
查看完整描述

3 回答

?
森栏

TA贡献1810条经验 获得超5个赞

你应该使用Dispatcher更新UI线程上的控件,并且正确地说,长时间运行的进程不应该在UI线程上运行。即使您在UI线程上异步运行长时间运行的进程,它仍然可能导致性能问题。

应该注意的是,Dispatcher.CurrentDispatcher它将返回当前线程的调度程序,而不一定是UI线程。我认为你可以使用它Application.Current.Dispatcher来获取对UI线程的调度程序的引用,如果你可以使用它,但如果没有,你将不得不将UI调度程序传递给你的后台线程。

通常我使用任务并行库进行线程操作而不是BackgroundWorker。我发现它更容易使用。

例如,

Task.Factory.StartNew(() => 
    SomeObject.RunLongProcess(someDataObject));

哪里

void RunLongProcess(SomeViewModel someDataObject){
    for (int i = 0; i <= 1000; i++)
    {
        Thread.Sleep(10);

        // Update every 10 executions
        if (i % 10 == 0)
        {
            // Send message to UI thread
            Application.Current.Dispatcher.BeginInvoke(
                DispatcherPriority.Normal,
                (Action)(() => someDataObject.ProgressValue = (i / 1000)));
        }
    }}


查看完整回答
反对 回复 2019-08-13
  • 3 回答
  • 0 关注
  • 287 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信