0

次のシナリオがあります。MVVM パターンに従う WPF C# プロジェクトを作成しました。さらに、ある種の画像ドロワーであるユーザー コントロールを開発しました。ここで、ビューモデル内にモデルを作成し、それを依存関係プロパティとしてユーザー コントロールと共有します。これは次のように行われます。

ユーザー制御:

public DXModel Model
    {
        get { return (DXModel)GetValue(ModelProperty); }
        set { SetValue(ModelProperty, value); }
    }

    public static readonly DependencyProperty ModelProperty =
        DependencyProperty.Register("Model", typeof(DXModel), typeof(DXControl),
                                    new PropertyMetadata(null, OnChanged));

    static void OnChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        (sender as DXControl).OnChanged();
    }

    void OnChanged()
    {
        if (Model != null)
            Model.PropertyChanged += new PropertyChangedEventHandler(Model_Changed);  // comes from the ui thread...comes only when init model...ok
        textTitle.Text = Model.Title;
        internalModel = (DXModel)Model;
    }

    void Model_Changed(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (!receiveTimer.Enabled)
        {
            receiveTimer.Interval = receiveDelay;
            receiveTimer.Start();
            refreshTimer.Start();
        }
    }

そのため、ビューモデルでモデルが変更されたときにもイベントを取得し、描画を実行します。基本的に、ビューモデル内で毎秒数回完全に上書きするポイントのリストがあります。

ビューモデル:

dxModel1.Series[0].Points = list1;

ユーザーコントロールでは、ポイントも毎秒数回再描画されます。そのためには、最初にポイントを反復処理する必要があります。

ユーザー制御:

int length = internalModel.Series[i].Points.Count-1;
float lastX = internalModel.Series[i].Points[0].X;
for (int j = 0; j <= length; j++)
    {
      float x = ((float)targetImage.Width - 0) / (internalModel.Axes[0].Max - internalModel.Axes[0].Min) * (internalModel.Series[i].Points[j].X- lastX - internalModel.Axes[0].Min);
      float y = (0 - (float)targetImage.Height) / (internalModel.Axes[1].Max - internalModel.Axes[1].Min) * (internalModel.Series[i].Points[j].Y - internalModel.Axes[1].Min) + (float)targetImage.Height;
      tmpPoints.Add(new SharpDX.Vector2(x, y));
    }

重要なのは、ビューモデル内のワーカー スレッドでモデルが変更されることです。ユーザー コントロールは ui スレッドに存在します。私が抱えている問題は、このポイントの反復により、時々例外が発生することです。これは、ワーカースレッドがポイントを反復すると同時に、ポイントが上書きされるためだと思います。

usercontrol 内の internalModel と viewmodel 内の dxModel1 をロックしようとしましたが、それは役に立ちませんでした。

なぜそれが失敗するのか、私のアプローチは正しいですか?もしそうなら、どうすればこの問題を克服できますか?

4

2 に答える 2

0

詳細を教えていただけなかったのでException、問題を完全に理解しているかどうかはわかりませんが、UI スレッドでコードが確実に実行されるようにしたい場合は、次のようにすることができます。

RunOnUiThread((Action)delegate()
{
    int length = internalModel.Series[i].Points.Count-1;
    float lastX = internalModel.Series[i].Points[0].X;
    for (int j = 0; j <= length; j++)
    {
        float x = ((float)targetImage.Width - 0) / (internalModel.Axes[0].Max - internalModel.Axes[0].Min) * (internalModel.Series[i].Points[j].X- lastX - internalModel.Axes[0].Min);
        float y = (0 - (float)targetImage.Height) / (internalModel.Axes[1].Max - internalModel.Axes[1].Min) * (internalModel.Series[i].Points[j].Y - internalModel.Axes[1].Min) + (float)targetImage.Height;
        tmpPoints.Add(new SharpDX.Vector2(x, y));
    }
});

...

public object RunOnUiThread(Delegate method)
{
    return Dispatcher.Invoke(DispatcherPriority.Normal, method);
}
于 2013-10-30T09:01:52.090 に答える