【发布时间】:2017-08-21 11:58:41
【问题描述】:
我开发了一个小项目(使用 MVVM),具有将文件上传到 FTP 服务器的功能。
用户可以查看上传进度:完成百分比由 vm.Busycontent 向用户显示,这是我的视图模型中的一个属性,绑定到我的视图中的 UI 元素。
这是读取文件并通过 FTP 上传的代码(它是任务 vm.FtpUploadTask 的一部分)
using (FileStream inputStream = File.OpenRead(file))
{
using (outputStream = request.GetRequestStream())
{
var buffer = new byte[1024 * 1024];
int totalReadBytesCount = 0;
int readBytesCount;
while ((readBytesCount = inputStream.Read(buffer, 0, buffer.Length)) > 0 && (!vm.Token.IsCancellationRequested))
{
vm.Token.ThrowIfCancellationRequested();
outputStream.Write(buffer, 0, readBytesCount);
totalReadBytesCount += readBytesCount;
var progress = totalReadBytesCount * 100.0 / inputStream.Length;
vm.BusyContent = ((int)progress).ToString();
}
}
}
MainWindow.xaml
我正在使用 WPF 扩展工具包 BusyIndicator
<xctk:BusyIndicator IsBusy='{Binding IsBusy}'>
<xctk:BusyIndicator.BusyContentTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text='{Binding Path=DataContext.BusyContent,
RelativeSource={RelativeSource AncestorType={x:Type Window}}}' />
</StackPanel>
</DataTemplate>
</xctk:BusyIndicator.BusyContentTemplate>
</xctk:BusyIndicator>
UploadToFTPCommand.cs
try
{
vm.FtpUploadTask = new Task(() => FTPUpload(file), vm.Token);
vm.FtpUploadTask.Start();
vm.FtpUploadTask.Wait(vm.Token);
vm.BusyContent = "upload done!";
}
catch (OperationCanceledException)
{
vm.BusyContent = "Canceled";
}
CancelCommand.cs
public class CancelCommand : ICommand
{
public void Execute(object parameter)
{
vm.TokenSource.Cancel();
}
}
取消功能有效,但有时 vm.Busycontent 等于
- ((int)progress).ToString()
- 在 uploadftp 命令中取消
当按下 Cancel 按钮时,while 循环应该退出并且用户应该只看到 catch 中的消息 (OperationCanceledException)。 任何想法如何解决这个问题?
注意事项
- 我使用的是 .NET 4.0
- 该程序是一个较大项目的一部分,其中包括多个应以同步方式执行的任务。这就是我使用 Task.Start() 和 Task.Wait() 方法的原因。
编辑 问题依旧
using (FileStream inputStream = File.OpenRead(file))
{
using (outputStream = request.GetRequestStream())
{
var buffer = new byte[1024 * 1024];
int totalReadBytesCount = 0;
int readBytesCount;
while ((readBytesCount = inputStream.Read(buffer, 0, buffer.Length)) > 0)
{
if (vm.Token.IsCancellationRequested)
{
break;
}
outputStream.Write(buffer, 0, readBytesCount);
totalReadBytesCount += readBytesCount;
var progress = totalReadBytesCount * 100.0 / inputStream.Length;
vm.BusyContent = ((int)progress).ToString();
}
if (vm.Token.IsCancellationRequested)
{
inputStream.Close();
outputStream.Close();
vm.Token.ThrowIfCancellationRequested();
}
}
}
【问题讨论】:
-
您正在检查
Token.IsCancellationRequested并在执行ThrowIfCancellationRequested()之前退出循环。 -
代码很多,能发minimal reproducible example吗?
-
@svick 我编辑我的问题以减少代码量
-
@JSteward 我已经编辑了我的代码,但问题仍然存在。有什么想法吗?
标签: wpf while-loop task-parallel-library task cancellation