[英]C# Thread-safe Extension Method
我可能会离开,或者非常接近。 无论哪种方式,我现在是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
//这里有什么?
mDispatcher.Invoke(new Action(() => sourceList.SetMyProperty(newValue)));
作为旁注,如果您需要检查当前线程是否可以访问UI,则无需比较线程ID。 您只需要调用CheckAccess
方法:
if (firstClass.Dispatcher.CheckAccess())
{
...
}
出于某种原因,这种方法隐藏在Intellisense中......不知道为什么
UPDATE
好吧,我的回答并不完全准确......你仍然需要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 });
}
}
}
请注意,我在泛型类型参数上添加了一个constaint,并且我删除了强制转换(你使用它的方式,泛型并没有带来任何好处)
只是为了清理上面例子中的几个小错别字(希望不加我自己的),这里是这个例子的最终解决方案。
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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.