从另一个Thread更新MainWindow中的进度条

我知道这个问题已被问过几次,我花了一整天时间试图理解其他答案,但由于我对C#和WPF很新,所以到目前为止没有任何帮助。 我将尝试尽可能多地解释我的确切问题,这将直接帮助我。

在我的MainWindow.xaml中,我有一个进度条和一些按钮启动一个新线程和一个长计算:

 

现在在我的MainWindow.xaml.cs中:

 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void button1_Click(object sender, RoutedEventArgs e) { Thread thread = new Thread(new ParameterizedThreadStart(MyLongCalculation)); ParameterClass myParameters = new ParameterClass(); thread.Start(myParameters); } public void MyLongCalculations(object myvalues) { ParameterClass values = (ParameterClass)myvalues; //some calculations } } public class ParameterClass { //public variables... } 

现在不知何故,我必须在我的方法MyLongCalculations中包含somethign,它将继续更新progressBar1 。 但是,我无法让它运作起来。 我知道这一切都很简单,但不幸的是,这是我目前使用C#的水平,所以我希望答案不要太复杂,尽可能详细。

背景工作者非常适合这一点。

试试这个:

 ///  /// Interaction logic for MainWindow.xaml ///  public partial class MainWindow : Window { public MainWindow() { // Initialize UI InitializeComponent(); // Process data ProcessDataAsync(new ParameterClass { Value = 20 }); } ///  /// Processes data asynchronously ///  ///  private void ProcessDataAsync(ParameterClass myClass) { // Background worker var myWorker = new BackgroundWorker { WorkerReportsProgress = true, }; // Do Work myWorker.DoWork += delegate(object sender, DoWorkEventArgs e) { // Set result e.Result = MyLongCalculations(myClass); // Update progress (50 is just an example percent value out of 100) myWorker.ReportProgress(50); }; // Progress Changed myWorker.ProgressChanged += delegate(object sender, ProgressChangedEventArgs e) { myProgressBar.Value = e.ProgressPercentage; }; // Work has been completed myWorker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e) { // Work completed, you are back in the UI thread. TextBox1.Text = (int) e.Result; }; // Run Worker myWorker.RunWorkerAsync(); } ///  /// Performs calculations ///  ///  ///  public int MyLongCalculations(ParameterClass myvalues) { //some calculations return (myvalues.Value*2); } } ///  /// Custom class ///  public class ParameterClass { public int Value { get; set; } } 

您可以使用Dispatcher.BeginInvoke()在UI线程而不是工作线程上推送UI更改。 最重要的是 – 您需要访问与UI线程关联的Dispatcher,而不是您手动创建的工作线程。 所以我建议缓存Dispatcher.Current ,然后在工作线程中使用,你可以通过ParametersClass或只在类级别声明一个dispatchr字段。

 public partial class MainWindow { private Dispatcher uiDispatcher; public MainWindow() { InitializeComponents(); // cache and then use in worker thread method this.uiDispatcher = uiDispatcher; } public void MyLongCalculations(object myvalues) { ParameterObject values = (ParameterObject)myvalues; this.uiDispatcher.BeginInvoke(/*a calculations delegate*/); } } 

此外,如果您需要在某个服务/类(如ParametersClass )中传递UI调度程序,我建议您看一下这个很好的SOpost ,它展示了如何通过一个接口来抽象它,能够同步/异步地推送UI更改,以便它将由调用者决定(基本上使用Invoke()BeginInvoke()在UI消息管道中对委托进行排队)。