我创建了一个小应用程序,使用基本的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简直停止):
Ihre App wurde angehalten,aber es gibt keinen anzuzeigenden Code, da alle Threads externenCodeausgeführthaben(normalerweise System- oder Frameworkcode)。
您的应用已停止,但没有代码可以显示,因为全部 线程运行外部代码(通常是System或Framworkcode)=&gt;这是我自己的翻译
当我使用 ContinueWith 进行此操作时,我得到相同的“异常”。使用 Task.WaitAll(),然后在UI线程中进行颜色设置会冻结UI。如何在不冻结UI的情况下重命名所有文件时如何更改颜色?
感谢您的帮助。
答案 0 :(得分:3)
您需要从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在评论中提到的,使用async
api正确完成了IO绑定操作。 See this reference关于如何进一步改进代码。给出的第一个例子是异步复制文件。