У меня есть приложение WPF с несколькими десятками пользовательских панелей, отображаемых в списке, каждая панель представляет задачу для выполнения. На каждой панели будут кнопки «Пуск» и «Стоп» для управления потоком.
Каждая панель включает в себя частного фонового работника для выполнения, и только один может выполняться одновременно, поскольку они получают доступ к общему ресурсу. Поэтому я хочу отключить кнопки на каждой панели, на которой не запускается задача, когда задача начинается на любой панели, и, разумеется, включить их снова, когда все будет завершено.
Итак, я хочу включить и отключить на основе 2 свойств:
1. Является ли переменная экземпляра частного фонового работника нулевой
2. Имеет ли публичный статический объект блокировку (полученную с помощью Monitor.Enter или lock)
Я хотел бы включить / отключить кнопки на основе следующей логики:
Кнопка «Пуск»:
- включено, если открытый объект не заблокирован (означает, что потоки не запущены), иначе отключен (хотя бы один поток, возможно, из этого класса, работает)
Кнопка «Стоп»
- Включено, если частный фоновый рабочий не равен NULL (поток из этого класса запускается / работает), иначе отключен (нет подходящих потоков для остановки)
Когда поток запускается, он получает блокировку на общем объекте и инициализирует локальный фоновый рабочий, который активирует одну кнопку остановки и отключает все остальные кнопки запуска.
Я довольно новичок в WPF и изучаю привязку данных. Я мог бы, вероятно, выяснить, как привязать к фоновому работнику == или! = Null, но я не уверен, как проверить, существует ли блокировка на объекте и как привязать к нему.
Примеры:
Вот пример кода, который следует за ответами, представленными ниже
Создание пользовательской панели с двумя кнопками (привязки для кнопки остановки не реализованы)
<StackPanel Orientation="Horizontal">
<Button Margin="2" x:Name="btnStart" Content="Start" Click="btnStart_Click" IsEnabled="{Binding CanCommandsExecute}"/>
<Button Margin="2" x:Name="btnStop" Content="Stop"/>
</StackPanel>
Поместите несколько экземпляров этого в окно
<StackPanel Orientation="Vertical">
<wpfsample:TestControl/>
<wpfsample:TestControl/>
<wpfsample:TestControl/>
</StackPanel>
А вот код для TestControl
public partial class TestControl : UserControl, INotifyPropertyChanged
{
private static bool IsLocked = false;
private static object threadlock = new object();
private BackgroundWorker _worker;
public event PropertyChangedEventHandler PropertyChanged;
private bool _canCommandsExecute = true;
public bool CanCommandsExecute {
get { return _canCommandsExecute && (!IsLocked); }
set { _canCommandsExecute = value; OnPropertyChanged("CanCommandsExecute"); } }
public TestControl()
{
DataContext = this;
InitializeComponent();
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
Monitor.Enter(threadlock);
try
{
IsLocked = true;
this.CanCommandsExecute = false;
_worker = new BackgroundWorker();
_worker.DoWork += (x, y) => { Thread.Sleep(5000); };
_worker.RunWorkerCompleted += WorkComplete;
_worker.RunWorkerAsync();
}
catch { Monitor.Exit(threadlock); }
}
private void WorkComplete(object sender, EventArgs e)
{
IsLocked = false;
this.CanCommandsExecute = true;
Monitor.Exit(threadlock);
}
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
Это частично решает вопрос. Когда вы нажимаете кнопку «Пуск», она отключает кнопку и запускает фоновую задачу. Это также делается с использованием привязки WPF, как и было запрошено.
Остается вопрос: как отключить ВСЕ кнопки запуска вместо одной? Я получаю блокировку статического объекта (который сейчас не работает, изучая это)
Надеюсь, этот пример поможет