简体   繁体   中英

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.

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.

How can I access and change UI form another thread and how to pass objects created in one thread to another? 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:

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

Start here: Build More Responsive Apps With The Dispatcher
and a little here: Beginners Guide to Threading in .NET: Part 5 of n
and a small example: Task Parallel Library: 1 of n

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

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();
      }
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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