Я относительно новичок в проектах C# WPF, и у меня есть проблема с моим кодом, благодаря чему пользовательский интерфейс «блокируется», пока я выполняю задачу. Вот соответствующий код:Предотвращение зависания GUI в 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
просто Slider
элемента интерфейса WPF; в то время как аналогичным образом 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
Без 'Dispatcher.Invoke' я получаю исключение времени выполнения о том, что вызывающий поток не может получить доступ к этому объекту, потому что другой поток владеет. Кроме того, 'GenerateAggregate' будет добавлять элементы в GUI (в конечном итоге), поэтому я понимаю, что мне нужно использовать' Dispatch.Invoke'. – ArchbishopOfBanterbury
Вам нужно отправить _only_ части, которые обновляют элементы управления пользовательским интерфейсом, а не весь метод. – Evk
А, я вижу, это имеет смысл. Я должен отметить: 'Generate' - это метод класса ManagedDLA2DContainer, который является кодом C++/CLI; действительно ли возможно обновить пользовательский интерфейс из оболочки C++/CLI? – ArchbishopOfBanterbury