简体   繁体   English

如何从另一个线程同步UI和访问对象?

[英]How to synchronize UI and access objects from another thread?

I'm quite new to parallel programming and threads. 我对并行编程和线程都很陌生。 I want to calculate and add series to a chart, which unfortunately is a quite time-consuming task. 我想计算并添加系列到图表,遗憾的是这是一项非常耗时的任务。 So I'd like to show a loading screen in the meantime: 所以我想在此期间显示一个加载屏幕:

(.NET 4.0, WPF for UI)

ShowLoadingScreen(true);
CalculateAndUpdateChart(chartControl, settings);
ShowLoadingScreen(false);
...
private void ShowLoadingScreen(bool show) { loadingScreen.IsBusy = show; }
private void CalculateAndUpdateChart(ChartControl chart, ProductSettings settings)
{
    chart.SomeSettings = ...
    foreach(var item in settings.Items)
    {
        chart.Series.Points.Add(CalculateItem(item));
        ...
    }
}

But of course that doesn't work. 但当然这不起作用。 So I guess I need to update the Chart control in another thread. 所以我想我需要在另一个线程中更新Chart控件。

ShowLoadingScreen(true);
Tash.Factory.StartNew(()=>{CalculateAndUpdateChart(chartControl, settings)});
ShowLoadingScreen(false);

However, now I get different errors, most of how I cannot access chartControl and settings from another thread. 但是,现在我得到了不同的错误,大多数我无法从另一个线程访问chartControl和设置。

How can I access and change UI form another thread and how to pass objects created in one thread to another? 如何从另一个线程访问和更改UI以及如何将在一个线程中创建的对象传递给另一个线程? Can you please give an analogous example of what I'm trying to do? 你能举一个类似的例子说明我想做什么吗?

From the non-UI thread to update a control on the UI thread, you must do: 从非UI线程更新UI线程上的控件,您必须执行以下操作:

Dispatcher.Invoke(...);  OR
Dispatcher.BeginInvoke(...);

Start here: Build More Responsive Apps With The Dispatcher 从这里开始: 使用Dispatcher构建更具响应性的应用程序
and a little here: Beginners Guide to Threading in .NET: Part 5 of n 还有一点: .NET中的线程初学者指南:n的第5部分
and a small example: Task Parallel Library: 1 of n 和一个小例子: 任务并行库:n中的1个

you must do maybe this one 你必须这样做

EDIT/Update 编辑/更新

this works fine for me, but de gui thread is still blocked for the time of computing 这对我来说很好,但de gui线程在计算时仍然被阻止

using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace TPLSpielwiese
{
  /// <summary>
  /// Interaction logic for MainWindow.xaml
  /// </summary>
  public partial class MainWindow : Window
  {
    public MainWindow() {
      this.InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e) {
      TaskScheduler taskUI = TaskScheduler.FromCurrentSynchronizationContext();
      Task.Factory
        .StartNew(() =>
                    {
                      this.ShowLoadingScreen(true);
                    }, CancellationToken.None, TaskCreationOptions.None, taskUI)
        .ContinueWith((t) =>
                        {
                          //CalculateAndUpdateChart(chartControl, settings);
                          Thread.Sleep(1000);
                        }, CancellationToken.None, TaskContinuationOptions.None, taskUI)
        .ContinueWith((t) =>
                        {
                          this.ShowLoadingScreen(false);
                        }, CancellationToken.None, TaskContinuationOptions.None, taskUI);
    }

    private Window loadScreen;

    private void ShowLoadingScreen(bool showLoadingScreen) {
      if (showLoadingScreen) {
        this.loadScreen = new Window() {Owner = this, WindowStartupLocation = WindowStartupLocation.CenterOwner, Width = 100, Height = 100};
        this.loadScreen.Show();
      } else {
        this.loadScreen.Close();
      }
    }
  }
}

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

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