我对并行编程和线程都很陌生。我想计算并添加系列到图表,遗憾的是这是一项非常耗时的任务。所以我想在此期间显示一个加载屏幕:
(.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,以及如何将在一个线程中创建的对象传递给另一个线程?你能给我一个类似的例子来说明我想做什么吗?
答案 0 :(得分:2)
从非UI线程更新UI线程上的控件,您必须执行以下操作:
Dispatcher.Invoke(...); OR
Dispatcher.BeginInvoke(...);
从这里开始:
Build More Responsive Apps With The Dispatcher
还有一点:Beginners Guide to Threading in .NET: Part 5 of n
还有一个小例子:Task Parallel Library: 1 of n
答案 1 :(得分:0)
你必须做这个
修改/更新强>
这对我来说很好,但是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();
}
}
}
}