Jor*_*enH 1 c# wpf mvvm async-await
我正在开发一个 .NET 4.5 小型 WPF/MVVM 项目,并且我正在尝试让进度条与 async/await 一起正确工作。
我已经一切正常,但无法正确取消任务。或者,我认为任务可能被取消,但进度条无论如何都会运行完整长度。
我在“开始”和“停止”上调用“LongRun”方法,但当我想停止时使用可选的取消令牌参数。这可能是一种不寻常的做事方式,但我认为它看起来不错 - 至少在理论上:-)
这是一些代码:
视图模型
public MainViewModel()
{
_progress = new Progress<int>(ReportProgress);
CountFilesCreatedCommand = new RelayCommand<IProgress<int>>(progress => LongRun(Progress));
_tokenSource = new CancellationTokenSource();
_tokenSource.Cancel();
StopCountFilesCommand = new RelayCommand<CancellationToken>(token => LongRun(Progress, _tokenSource.Token));
ProgressText = "...";
}
private void ReportProgress(int result)
{
PercentProgress = result;
}
private async void LongRun(IProgress<int> progress, CancellationToken token = default(CancellationToken))
{
try
{
// Start long running task here
int i = 0;
for (; i != 101; ++i)
{
if (token.IsCancellationRequested)
{
// This part of the code is executed when I
// try to stop the Task, I can see the "Cancelled!"
// text flicker for a second, and then the code
// resume to run
_tokenSource.Cancel();
progress?.Report(PercentProgress);
ProgressText = "Cancelled!";
}
await Task.Delay(TimeSpan.FromSeconds(0.1), token).ConfigureAwait(false);
progress?.Report(i);
ProgressText = i + "%";
}
}
catch (OperationCanceledException)
{
//throw;
}
}
Run Code Online (Sandbox Code Playgroud)
XAML
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<StackPanel>
<!--<Button Margin="10,18,10,0" Content="Start Long Run" Height="30" Click="Button_Click_Async"/>-->
<ProgressBar x:Name="pbStatus" Margin="10,10,10,0" Height="30" IsIndeterminate="False" Visibility="Visible" Minimum="0" Maximum="100" Value ="{Binding PercentProgress, Mode=TwoWay}"/>
<TextBlock x:Name="tbResultat" Margin="0,10,0,10" HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding ProgressText}" />
<DockPanel>
<Button Margin="10,0" Content="Start Long Run" Height="30" Width="200" Command="{Binding CountFilesCreatedCommand}"/>
<Button Margin="10,0" Content="Stop Long Run" Height="30" Width="200" HorizontalAlignment="Right" Command="{Binding StopCountFilesCommand}"/>
</DockPanel>
</StackPanel>
</Grid>
Run Code Online (Sandbox Code Playgroud)
我感觉该解决方案可能与 XAML 有关?
任何帮助将不胜感激!
我在“开始”和“停止”上调用“LongRun”方法,但当我想停止时使用可选的取消令牌参数。
这就是你的问题所在。当您停止时,您希望现有的调用LongRun
存在,而不是创建新的调用LongRun
。
像这样的事情会更合适(假设此操作只能完成一次,并且您根据需要启用/禁用按钮):
_progress = new Progress<int>(ReportProgress);
_tokenSource = new CancellationTokenSource();
CountFilesCreatedCommand = new RelayCommand(() => LongRun(_progress, _tokenSource.Token));
StopCountFilesCommand = new RelayCommand(() => _tokenSource.Cancel());
ProgressText = "...";
Run Code Online (Sandbox Code Playgroud)
顺便说一句,您应该避免async void
(正如我在 MSDN 文章中所描述的那样)。async void
具有尴尬的错误处理语义并且不可进行单元测试。
归档时间: |
|
查看次数: |
2176 次 |
最近记录: |