簡體   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