繁体   English   中英

等待任务完成而不阻塞UI,奇怪的异常

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM