繁体   English   中英

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

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

我对并行编程和线程都很陌生。 我想计算并添加系列到图表,遗憾的是这是一项非常耗时的任务。 所以我想在此期间显示一个加载屏幕:

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

但当然这不起作用。 所以我想我需要在另一个线程中更新Chart控件。

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

但是,现在我得到了不同的错误,大多数我无法从另一个线程访问chartControl和设置。

如何从另一个线程访问和更改UI以及如何将在一个线程中创建的对象传递给另一个线程? 你能举一个类似的例子说明我想做什么吗?

从非UI线程更新UI线程上的控件,您必须执行以下操作:

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

从这里开始: 使用Dispatcher构建更具响应性的应用程序
还有一点: .NET中的线程初学者指南:n的第5部分
和一个小例子: 任务并行库:n中的1个

你必须这样做

编辑/更新

这对我来说很好,但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