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;
            }
        }
    }
}

显然,我正在扩展方法中寻找“这里有什么”。

谢谢,wTS

4

2 回答 2

1

// 这里发生了什么?

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

附带说明,如果您需要检查当前线程是否可以访问 UI,则无需比较线程 ID。您只需要调用该CheckAccess方法:

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

出于某种原因,这种方法隐藏在 Intellisense 中......不知道为什么


更新

好的,我的回答并不完全准确......您仍然需要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 回答