我正在查看this code我希望与Xamarin.iOS / Android一起使用的可观察词典。有评论和答案表明并发性并不是一个问题。
一般来说,在处理实现INotifyPropertyChanged的对象时,我应该依赖什么线程安全保证?
换句话说,:
当使用UI线程中的可观察字典时,该对象是否也必须是线程安全的?
如果在UI线程上没有管理字典怎么办?
我正在考虑替代实施
答案 0 :(得分:1)
一般来说,在处理实现INotifyPropertyChanged的对象时,我应该依赖什么线程安全保证?
当一个对象实现INotifyPropertyChanged
接口时,它的成员PropertyChanged
是一个拦截属性改变动作的事件处理程序,应该在我们的代码中实现,然后我们还需要创建方法/函数处理此事件,从而确保多个线程在操作此对象时不会发生冲突。例如:
public class Test1 : INotifyPropertyChanged
{
private string _test;
public string test
{
get { return _test; }
set
{
if (value != _test)
{
_test = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName]string propertyName = "")
{
if (this.PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
现在问题是PropertyChanged
事件如何保证其安全,如果您使用ILSpy
来检查INotifyPropertyChanged Interface的源代码,您会发现其内部只是实现了委托PropertyChanged
,委托是这样的:
using System;
using System.Security.Permissions;
namespace System.ComponentModel
{
/// <summary>Represents the method that will handle the <see cref="E:System.ComponentModel.INotifyPropertyChanged.PropertyChanged" /> event raised when a property is changed on a component.</summary>
/// <param name="sender">The source of the event. </param>
/// <param name="e">A <see cref="T:System.ComponentModel.PropertyChangedEventArgs" /> that contains the event data. </param>
[__DynamicallyInvokable]
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
public delegate void PropertyChangedEventHandler(object sender, PropertyChangedEventArgs e);
}
您应该能够发现此委托上方有HostProtection
属性,此属性允许使用声明性安全措施来确定主机保护要求。在此HostProtectionAttribute : CodeAccessSecurityAttribute
的实现中,它创建了线程同步锁。以下是它的部分代码:
/// <summary>Gets or sets a value indicating whether synchronization is exposed.</summary>
/// <returns>true if synchronization is exposed; otherwise, false. The default is false.</returns>
public bool Synchronization
{
get
{
return (this.m_resources & HostProtectionResource.Synchronization) > HostProtectionResource.None;
}
set
{
this.m_resources = (value ? (this.m_resources | HostProtectionResource.Synchronization) : (this.m_resources & ~HostProtectionResource.Synchronization));
}
}
/// <summary>Gets or sets a value indicating whether shared state is exposed.</summary>
/// <returns>true if shared state is exposed; otherwise, false. The default is false.</returns>
public bool SharedState
{
get
{
return (this.m_resources & HostProtectionResource.SharedState) > HostProtectionResource.None;
}
set
{
this.m_resources = (value ? (this.m_resources | HostProtectionResource.SharedState) : (this.m_resources & ~HostProtectionResource.SharedState));
}
}
所以对于你的问题:
当使用UI线程中的可观察字典时,该对象是否也必须是线程安全的?
如果未在UI线程上管理词典会怎样?
在UI线程中,如果代码中没有跨线程变量访问,那么它是安全的,否则会导致不安全。当不在UI线程中时,我们需要使用invoke方式(UI Dispatcher)将操作推送到UI线程。