C# 线程安全扩展方法
我可能已经离开了,或者真的很接近了。不管怎样,我目前是 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;
}
}
}
}
显然,我正在扩展方法中寻找“这里有什么”。
谢谢, 工作时间
I may be waaaay off, or else really close. Either way, I'm currently SOL. :)
I want to be able to use an extension method to set properties on a class, but that class may (or may not) be updated on a non-UI thread, and derives from a class the enforces updates to be on the UI thread (which implements INotifyPropertyChanged, etc).
I have a class defined something like this:
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; }
}
}
I have an extension method class defined something like this:
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;
}
}
}
}
Obviously, I'm looking for the "WHAT GOES HERE" in the extension method.
Thanks,
wTs
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
附带说明一下,如果您需要检查当前线程是否有权访问 UI,则无需比较线程 ID。您只需要调用
CheckAccess
方法:出于某种原因,此方法隐藏在 Intellisense 中...不知道为什么
更新
好吧,我的答案并不完全准确...您仍然需要 < code>yield return 集合中的每一项,而 Invoke 不会这样做。这是您的方法的另一个版本:
请注意,我在泛型类型参数上添加了一个约束,并且删除了强制转换(按照您的方式,泛型没有带来任何好处)
As a side note, if you need to check whether the current thread has access to the UI, you don't need to compare thread ids. You just need to call the
CheckAccess
method :For some reason, this methods is hidden in Intellisense... no idea why
UPDATE
OK, my answer wasn't totally accurate... you still need to
yield return
each item of the collection, and Invoke doesn't do it. Here's another version of your method :Note that I added a constaint on the generic type parameter, and I removed the casts (the way you were doing it, generics didn't bring any benefit)
只是为了清理上面示例中的几个小拼写错误(希望不要添加我自己的拼写错误),这是该示例的最终解决方案。
Just to clean up a couple of small typos (and hopefully not add my own) in the above example, here is a final solution to the example.