3

私はちょっと離れているかもしれませんし、そうでなければ本当に近いです。いずれにせよ、私は現在SOLです。:)

拡張メソッドを使用してクラスのプロパティを設定できるようにしたいのですが、そのクラスは非 UI スレッドで更新される可能性があり (または更新されない可能性があります)、UI スレッドで更新を強制するクラスから派生します (これは INotifyPropertyChanged などを実装します)。

次のようなクラスを定義しています。

public class ClassToUpdate : UIObservableItem
{
    private readonly Dispatcher mDispatcher = Dispatcher.CurrentDispatcher;
    private Boolean mPropertyToUpdate = false;

    public ClassToUpdate() : base()
    {
    }

    public Dispatcher Dispatcher
    {
        get { return mDispatcher; }
    }

    public Boolean PropertyToUpdate
    {
        get { return mPropertyToUpdate; }
        set { SetValue("PropertyToUpdate", ref mPropertyToUpdate, value; }
    }
}

次のように定義された拡張メソッド クラスがあります。

static class ExtensionMethods
{
    public static IEnumerable<T> SetMyProperty<T>(this IEnumerable<T> sourceList,
                                                  Boolean newValue)
    {
       ClassToUpdate firstClass = sourceList.FirstOrDefault() as ClassToUpdate;

       if (firstClass.Dispatcher.Thread.ManagedThreadId != 
           System.Threading.Thread.CurrentThread.ManagedThreadId)
        {
            // WHAT GOES HERE?
        }
        else
        {
            foreach (var classToUpdate in sourceList)
            {
               (classToUpdate as ClassToUpdate ).PropertyToUpdate = newValue;
               yield return classToUpdate;
            }
        }
    }
}

明らかに、拡張メソッドで「WHAT GOES HERE」を探しています。

ありがとう、wTs

4

2 に答える 2

1

// ここに何が入る?

mDispatcher.Invoke(new Action(() => sourceList.SetMyProperty(newValue)));

補足として、現在のスレッドが UI にアクセスできるかどうかを確認する必要がある場合、スレッド ID を比較する必要はありません。CheckAccessメソッドを呼び出すだけです:

if (firstClass.Dispatcher.CheckAccess())
{
    ...
}

何らかの理由で、このメソッドは Intellisense に隠されています...理由がわかりません


アップデート

OK、私の答えは完全に正確ではありませんでした...yield returnコレクションの各アイテムが必要ですが、Invoke はそれを行いません。メソッドの別のバージョンは次のとおりです。

public static IEnumerable<T> SetMyProperty<T>(this IEnumerable<T> sourceList, bool newValue)
    where T : ClassToUpdate
{
    Action<T> setProperty = t => t.PropertyToUpdate = newValue;

    foreach(var t in sourceList)
    {
        if (t.Dispatcher.CheckAccess())
        {
            action(t);
        }
        else
        {
            t.Dispatcher.Invoke(action, new object[] { t });
        }
    }
}

ジェネリック型パラメーターに制約を追加し、キャストを削除したことに注意してください(あなたが行っていた方法では、ジェネリックは何の利益ももたらしませんでした)

于 2010-04-05T22:46:09.617 に答える
0

上記の例のいくつかの小さなタイプミスをクリーンアップするためだけに (そして、できれば自分のタイプミスを追加しないでください)、この例の最終的な解決策を次に示します。

public static IEnumerable<T> SetMyProperty<T>(this IEnumerable<T> sourceList, 
    bool newValue) where T : ClassToUpdate
{
    Action<T> setProperty = t => t.PropertyToUpdate = newValue;

    foreach(var t in sourceList)
    {
        if (t.Dispatcher.CheckAccess())
        {
            setProperty(t);
        }
        else
        {
            t.Dispatcher.Invoke(setProperty, new object[] { t });
        }

        yield return t;
    }
}
于 2010-04-07T15:00:50.323 に答える