[英]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.