[英]Wait for task to finish without blocking the UI, strange exception
我创建了一个小应用程序,以使用基本的mvvm模式重命名某些文件。 这些文件将使用新名称复制到新文件夹,并且有一个进度条(成功显示)。 由于有很多文件,因此我通过Task.Factory.StartNew(...)完成此操作 。 进度条的颜色为橙色; 重命名所有文件后,颜色应变为绿色。
这是xaml的一部分:
<ProgressBar x:Name="pBar" HorizontalAlignment="Left" Height="20" Margin="10,5" Foreground="{Binding ProgBarBrush}" VerticalAlignment="Top" Width="100" Value="{Binding ProgBarValue}" Maximum="{Binding MaxIndex}"/>
视图模型:
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };
private int _maxIndex;
public int MaxIndex
{
get { return _maxIndex; }
set
{
if (value == _maxIndex)
return;
_maxIndex = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(MaxIndex)));
}
}
private int _pBarValue;
public int ProgBarValue
{
get { return _pBarValue; }
set
{
if (value == _pBarValue)
return;
_pBarValue = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ProgBarValue)));
}
}
private SolidColorBrush _brush;
public SolidColorBrush ProgBarBrush
{
get { return _brush; }
set
{
if (value == _brush)
return;
_brush = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ProgBarBrush)));
}
}
}
任务:
private void StartRename_Click(object sender, RoutedEventArgs e)
{
var newDir = dir + @"\Renamed";
Directory.CreateDirectory(newDir);
vm.ProgBarValue = 0;
vm.ProgBarBrush = new SolidColorBrush(Colors.Orange);
Task t1 = Task.Factory.StartNew(() =>
{
foreach (var pic in pics)
{
if (File.Exists(newDir + @"\" + pic.newName))
{
MessageBox.Show("File " + newDir + @"\" + pic.newName + " already exists. Skipping remaining files...", "File already exists");
return;
}
File.Copy(pic.fileInfo.FullName, newDir + @"\" + pic.newName);
vm.ProgBarValue++;
}
vm.ProgBarBrush = new SolidColorBrush(Colors.Green);
});
}
绑定有效-进度条的值更改,并且UI线程中的第一个颜色更改为橙色。 这些文件也按照我想要的方式进行复制和重命名。 但是当我像这样进行颜色更改时,我得到一个奇怪的“异常”(Visual Studio 2017只是停止了):
在应用程序中,应用程序代码在外部代码中是正常代码系统框架代码)。
您的应用已暂停,但由于所有线程都运行了外部代码(通常是System或Framworkcode),所以没有任何代码可供显示=>这是我自己的翻译
当我使用ContinueWith进行操作时,我得到了相同的“异常”。 使用Task.WaitAll() ,然后在UI线程中进行颜色设置将冻结UI。 重命名所有文件而不冻结UI时如何更改颜色?
谢谢你的帮助。
您需要从UI线程更改进度栏的颜色和值。 您可以使用async/await
轻松完成此操作,如本示例所示。 另外,我使用IProgress
更新了进度。
private async void StartRename_Click(object sender, RoutedEventArgs e)
{
var newDir = dir + @"\Renamed";
Directory.CreateDirectory(newDir);
vm.ProgBarValue = 0;
vm.ProgBarBrush = new SolidColorBrush(Colors.Orange);
var progress = new Progress<int>(_ => vm.ProgBarValue++)
await Task.Run(() =>
{
foreach (var pic in pics)
{
if (File.Exists(newDir + @"\" + pic.newName))
{
MessageBox.Show("File " + newDir + @"\" + pic.newName + " already exists. Skipping remaining files...", "File already exists");
return;
}
File.Copy(pic.fileInfo.FullName, newDir + @"\" + pic.newName);
progress.Report(1);
}
});
vm.ProgBarBrush = new SolidColorBrush(Colors.Green);
}
正如@ckuri在评论中提到的,IO绑定操作是通过async
api正确完成的。 有关如何进一步改进代码, 请参见此参考 。 给出的第一个示例是异步复制文件的示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.