Because MoveZ
returns a Task
, it should be awaited.
You should not pause a Task
or thread or a method in general. Especially when you don't know for how long. Better cancel the Task
and restart it. You can always use events to control a "non-linear" flow.
Maybe you should consider to execute MoveZ
on a background thread and post the incremented value back to the UI using IProgress<T>
:
You need to know: Dependency Property Overview and Data Binding Overview and Async in 4.5: Enabling Progress and Cancellation in Async APIs.
MainWindow.xaml.cs
public static readonly DependencyProperty StopValueProperty = DependencyProperty.Register(
"StopValue",
typeof(double),
typeof(MainWindow),
new PropertyMetadata(default(double)));
public double StopValue
{
get => (double) GetValue(MainWindow.StopValueProperty);
set => SetValue(MainWindow.StopValueProperty, value);
}
public static readonly DependencyProperty StepValueProperty = DependencyProperty.Register(
"StepValue",
typeof(double),
typeof(MainWindow),
new PropertyMetadata(default(double)));
public double StepValue
{
get => (double) GetValue(MainWindow.StepValueProperty);
set => SetValue(MainWindow.StepValueProperty, value);
}
public static readonly DependencyProperty BreakValueProperty = DependencyProperty.Register(
"BreakValue",
typeof(double),
typeof(MainWindow),
new PropertyMetadata(default(double), MainWindow.OnBreakValueChanged));
public double BreakValue
{
get => (double) GetValue(MainWindow.BreakValueProperty);
set => SetValue(MainWindow.BreakValueProperty, value);
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value",
typeof(double),
typeof(MainWindow),
new PropertyMetadata(default(double)));
public double Value
{
get => (double) GetValue(MainWindow.ValueProperty);
set => SetValue(MainWindow.ValueProperty, value);
}
private CancellationTokenSource CancellationTokenSource { get; set; }
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private static void OnBreakValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var this_ = d as MainWindow;
if (this_.Value == this_.BreakValue)
{
// Cancel MoveZ()
this_.CancellationTokenSource.Cancel();
return;
}
// Task was canceled before --> restart procedure
if (this_.CancellationTokenSource.IsCancellationRequested)
{
this_.StartMoveZ();
}
}
private void MoveZ(IProgress<double> progressReporter, CancellationToken cancellationToken)
{
Task.Run(
async () =>
{
for (; this.Value <= this.StopValue; this.Value += this.StepValue)
{
progressReporter.Report(this.Value);
cancellationToken.ThrowIfCancellationRequested();
await Task.Delay(2000, cancellationToken);
}
}, cancellationToken);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Value = 0;
StartMoveZ();
}
private void StartMoveZ()
{
this.CancellationTokenSource = new CancellationTokenSource();
var progressReporter = new Progress<double>(value => zpos.Text = value);
MoveZ(progressReporter, this.CancellationTokenSource.Token);
}
MainWindow.xaml
<Window>
<StackPanel>
<TextBox Text="{Binding StopValue}" />
<TextBox Text="{Binding BreakValue}" />
<TextBox Text="{Binding StepValue}" />
<Button Content="Start" Click="Button_Click" />
<TextBlock Text="{Binding Value}" />
</StackPanel>
</Window>