我对C#WPF项目相对较新,我的代码存在问题,用户界面"锁定"我正在执行一项任务。以下是相关代码:
public partial class MainWindow : Window {
// handles to ManagedDLAContainer objects
private ManagedDLA2DContainer dla_2d;
public MainWindow() {
InitializeComponent();
// initalise aggregate containers
dla_2d = new ManagedDLA2DContainer();
}
private void GenerateAggregate() {
// generate the 2D aggregate of size given by particles_slider value
Dispatcher.Invoke(new Action(() => { dla_2d.Generate((uint)particles_slider.Value); }));
// TODO: add particles to "canvas" on GUI as they are generated
}
private void GenerateButtonClick(object sender, RoutedEventArgs e) {
// set the coefficient of stickiness of aggregate
// to current value of stickiness_slider
dla_2d.SetCoeffStick(stickiness_slider.Value);
// start asynchronous task calling GenerateAggregate method
Task.Factory.StartNew(() => GenerateAggregate());
}
}
此处ManagedDLA2DContainer
是一些托管C++/CLI
包装,用于某些原生的非托管C++
代码,而stickiness_slider
只是WPF界面的Slider
元素;同样,particles_slider
是界面的另一个Slider元素。我应该注意,以下代码也会导致GUI挂起:
public partial class MainWindow : Window {
// lock object for multi-threading tasks
private static readonly object locker = new object();
// handles to ManagedDLAContainer objects
private ManagedDLA2DContainer dla_2d;
public MainWindow() {
InitializeComponent();
// initalise aggregate containers
dla_2d = new ManagedDLA2DContainer();
}
private void GenerateAggregate() {
// lock around aggregate generation
lock (locker) {
// generate the 2D aggregate of size given by particles_slider value
Dispatcher.Invoke(new Action(() => { dla_2d.Generate((uint)particles_slider.Value); }));
// TODO: add particles to "canvas" on GUI as they are generated
}
}
private void GenerateButtonClick(object sender, RoutedEventArgs e) {
// set the coefficient of stickiness of aggregate
// to current value of stickiness_slider
dla_2d.SetCoeffStick(stickiness_slider.Value);
Thread agg_gen_thread = new Thread(GenerateAggregate);
agg_gen_thread.Start();
agg_gen_thread.Join();
}
}
任何可以帮助我理解我在这里做错的信息都值得赞赏。
此外,如果您感到好奇,那么此项目的所有代码都可在此处获取:https://github.com/SJR276/DLAProject
答案 0 :(得分:1)
您启动运行GenerateAggregate
的新主题。然后立即通过Dispatcher.Invoke
将所有工作返回发送到用户界面线程。所以基本上你在UI线程上运行长时间运行的任务并阻止它。
相反,您应该仅向UI线程调度需要的操作(例如,更新UI控件),而不是整个操作。
假设您的Generate函数如下所示:
void Generate() {
MakeCpuIntensiveWork();
UpdateUIWithResults();
}
您只需要将第二部分发送到UI线程。在您的情况下,正如我们在评论中发现的那样,唯一的UI部分是获得滑块的值。所以你可以像这样分开:
private void GenerateAggregate()
{
uint sliderValue = 0;
// generate the 2D aggregate of size given by particles_slider value
Dispatcher.Invoke(() => { sliderValue = (uint)particles_slider.Value; });
dla_2d.Generate(sliderValue);
// TODO: add particles to "canvas" on GUI as they are generated
}