簡體   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