2

私は UserControl を再利用しようとしていますが、進行状況を追跡するロジックも借りています。物事を単純化しようとします。MyWindow.xaml には MyUserControl が含まれています。MyUserControl には独自の進行状況インジケーター (フォーマット中...、ファイルのコピー中... など) があり、この進行状況を MyWindow フォームのどこかにミラーリングしたいと思います。しかし、ユーザー コントロールには、よくわからないロジックがあります。何度も読みましたが、まだ Dispatcher を理解していません。進行状況を更新するユーザー コントロールのロジックの概要を次に示します。

this.Dispatcher.Invoke(DispatcherPriority.Input, (Action)(() =>
{
   DAProgressIndicator = InfiniteProgress.AddNewInstanceToControl(StatusGrid, new SolidColorBrush(new Color() { A = 170, R = 128, G = 128, B = 128 }), string.Empty);
                DAProgressIndicator.Message = MediaCardAdminRes.ActivatingCard;
                ActivateInProgress = true;
}));

私は賢いと思い、ActivateInProgress プロパティ セット ロジックで呼び出される MyUserControl にイベントを追加しました。

   public bool ActivateInProgress 
   {
      get
      {
         return _activateInProgress;
      }
      set
      {
         _activateInProgress = value;
         if (ActivateInProgressHandler != null)
         {
            ActivateInProgressHandler(value);
         }
      }
   }

MyWindow コンストラクター内の ActivateInProgressHandler を、ウィンドウ自体の進行状況インジケーターに使用されるビュー モデル プロパティを設定する次のメソッドに設定しています。

private void SetActivation(bool activateInProgress)
{
   viewModel.ActivationInProgress = activateInProgress;
}

ただし、ウィンドウの進行状況インジケーターは変化しません。だから、私は Dispatcher.Invoke が私が理解できないことをしていると確信しています。SetActivation メソッド内にメッセージ ボックスを配置すると、スレッドがブロックされ、ウィンドウの進行状況インジケーターが更新されます。基本的なスレッドは理解していますが、この Dispatcher 全体は初めてです。私は何が欠けていますか?

更新: 現在は機能しているようです。進行状況が非常に速く更新されたため、画面に表示されなかったことが判明しました。しかし、なぜ Dispatcher.Invoke が実行されたのかを理解したいと思います (これは私が書いていない既存のコードでした)。アクションの内容が *.xaml.cs コードの残りの部分と一致しないのはなぜですか?

4

2 に答える 2

1

最後の段落でスレッドが 2 回言及されているため、バックグラウンド スレッドが 1 つ以上存在する可能性があります。しかし、アプリケーションに存在するスレッド、それらがどのように作成され、どのように相互作用するかなどについて言及していないので、ここではスレッドが 1 つしかないと仮定します。

UI スレッドが唯一のスレッドである場合、問題は明らかです。UI スレッドは進行中のタスクの実行でビジーであり、更新された UI をレンダリングするのに時間がかかりません。それが問題である場合、これはおそらくそれを修正します:

viewModel.ActivationInProgress = activateInProgress; 
Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle,
                       new Action(() => {}));

BeginInvoke は、現在のスレッドが続行される前に、入力優先度を超えるすべての Dispatcher 操作を強制的に完了させます。

于 2010-06-15T06:18:02.953 に答える
0

Dispatcher はキューで動作します。そのため、UI スレッドがブロックされている可能性があります。Dispatcher を介してキューに作業を追加しますが、UI スレッドがブロックされているため、実行されません。

多分これを試してください:

DispatcherFrame _frame = new DispatcherFrame();
Dispatcher.PushFrame(_frame);

これにより、既にキューにある作業の前に作業が配置されます。そのため、UI スレッドが作業を行ってから、再びブロックします。

于 2010-06-16T05:22:17.423 に答える