1

プログレスバーがあり、その値はプロパティにバインドされています:

                <ProgressBar x:Name="progressBar"
                         Margin="0,2,0,0"
                         Height="20"
                         Value="{Binding CompassLogLoadPercent}"
                         Foreground="Blue"
                         Visibility="{Binding CompassLogLoadCompleted, 
                Converter={StaticResource BooleanToVisibilityConverter}}"
                         ToolTip="Loading">
            </ProgressBar>

およびプロパティ:

       public double CompassLogLoadPercent {
        get { return _compassLogLoadPercent; }
        private set {
            if (value != _compassLogLoadPercent) {
                _compassLogLoadPercent = value;
                NotifyPropertyChanged();
            }
        }
    }

別のスレッドで、その値が更新されます。

   for (int j = 0; j < lines.Count(); j++) {
      ...
      CompassLogLoadPercent = ((double) j /lines.Count())*100;
   }

スレッドは TASK を使用して作成されます。

Task.Run(() => { LoadLogFile(fileName); });

プログレスバーが更新されないのはなぜですか? これを修正するにはどうすればよいですか?

更新詳細情報

Datacontext: (dataContext が正しいと確信しています)

cLT.progressBar.DataContext = logSession;

の実装INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void NotifyPropertyChanged(
        [CallerMemberName] String propertyName = "") {
        PropertyChangedEventHandler eventHandler = PropertyChanged;

        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
4

1 に答える 1

4

問題は、あなたが示していない何かのどこかにあります。基本は音です。(特に、PropertyChangedワーカー スレッドでイベント通知を発生させることに問題はありません。これは、WPF のデータ バインディング システムがその発生を検出し、UI スレッドでターゲット UI 要素を更新するように自動的に調整するためです。)

動作する完全な例を次に示します。XAML は次のとおりです。

<Window x:Class="BackgroundThreadUpdate.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ProgressBar
            x:Name="progressBar"
            VerticalAlignment="Top" Height="20"
            Value="{Binding CompassLogLoadPercent}">
        </ProgressBar>
        <Button Content="Button" HorizontalAlignment="Left" Margin="10,25,0,0" VerticalAlignment="Top"
                Width="75" RenderTransformOrigin="-1.24,-0.045" Click="Button_Click_1"/>

    </Grid>
</Window>

コードビハインドは次のとおりです。

using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace BackgroundThreadUpdate
{
    public partial class MainWindow : Window
    {
        private MySource _src;
        public MainWindow()
        {
            InitializeComponent();
            _src = new MySource();
            DataContext = _src;
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            Task.Run(() =>
            {
                for (int i = 0; i < 100; ++i)
                {
                    Thread.Sleep(100);
                    _src.CompassLogLoadPercent = i;
                }
            });
        }
    }

    public class MySource : INotifyPropertyChanged
    {
        private double _compassLogLoadPercent;
        public double CompassLogLoadPercent
        {
            get
            {
                return _compassLogLoadPercent;
            }
            set
            {
                if (_compassLogLoadPercent != value)
                {
                    _compassLogLoadPercent = value;
                    OnPropertyChanged("CompassLogLoadPercent");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

これは、使用しようとしている手法の実用的なバージョンを示しています。

したがって、あなたが機能しないという事実は、あなたが私たちに示していない何かが原因であるに違いありません. いくつかの可能な説明:

  • UI スレッドがブロックされている可能性があります。UI スレッドがビジー状態の場合、データ バインディングの更新は処理されません。(データ バインディングは、ワーカー スレッド上のデータ ソースからの変更を検出すると、関連するディスパッチャー スレッドにメッセージを送信します。ディスパッチャー スレッドがビジー状態の場合、そのメッセージは処理されません。)
  • データ ソースが適切でない可能性があります。コンテキストを設定した場所を示していないDataContextためProgressBar、間違っている可能性があります。
  • PropertyChangedイベントを発生させるコード (NotifyPropertyChangedコード) が間違っている可能性があります。そのコードを示していないため、イベントを発生させるときに使用するプロパティ名をどのように認識しているかが明確ではありません。

最初のものを確認するには、このバックグラウンド作業の進行中に UI がユーザー入力に応答するかどうかを確認します。そうでない場合は、それが更新がうまくいかない理由です。

関連リンクを追加するために 2 月 25 日に更新

このシナリオを処理する方法について他に何が言えるかを考えたところ、大きすぎて 1 つの StackOverflow の回答に収まらないという結論に達しました。そのため、UI に情報をロードする必要があるバックグラウンド スレッドで重要な処理を行う場合のパフォーマンスに関する考慮事項について、一連のブログ記事を書きました: http://www.interact-sw.co.uk/iangblog/2013/02/ 14/wpf-async-速すぎる

于 2013-02-11T10:52:21.667 に答える