Я создал класс, который содержит конфигурацию приложения, так что несколько потоков могут получить доступ к значениям в нем. Очевидно, что я выполняю блокировку внутри свойств и методов, которые устанавливают или читают эти значения.Как предотвратить другие потоки, чтобы изменить строку?
public class Settings
{
private readonly object m_BackupServersLocker = new object();
private readonly List<Uri> m_BackupServers = new List<Uri>();
private readonly object m_ExcludedFileExtensionsLocker = new object();
private readonly List<string> m_ExcludedFileExtensions = new List<string>();
/// <summary>
/// The working threads use this property to get the addresses of the remote backup servers.
/// </summary>
public IEnumerable<Uri> RemoteBackupServers
{
get
{
lock (m_RemoteBackupServersLocker)
{
List<Uri> endpoints = new List<Uri>();
foreach (var uri in m_RemoteBackupServers)
{
string uriString = string.Copy(uri.ToString());
endpoints.Add(new Uri(uriString));
}
return endpoints;
}
}
}
/// <summary>
/// This method is invoked by the thread which reads the configuration from file.
/// </summary>
/// <param name="uri"></param>
public bool InsertRemoteBackupServer(Uri uri)
{
lock (m_RemoteBackupServersLocker)
{
if (uri == null) return false;
return m_RemoteBackupServers.Add(uri);
}
}
/// <summary>
/// This method is invoked by the thread which reads the configuration from file.
/// </summary>
/// <param name="uri"></param>
/// <returns></returns>
public bool RemoveRemoteBackupServer(Uri uri)
{
lock (m_RemoteBackupServersLocker)
{
if (uri == null) return false;
return m_RemoteBackupServers.Remove(uri);
}
}
/// <summary>
/// The working threads use the property to get the list of excluded extensions.
/// The property is also invoked by the thread which reads the configuration from file, in order to update the exclusion list.
/// </summary>
public IEnumerable<string> ExcludedFileExtensions
{
get
{
lock (m_ExcludedFileExtensionsLocker)
{
List<string> temp = new List<string>();
foreach (var extension in m_ExcludedFileExtensions)
{
string extString = string.Copy(extension);
temp.Add(extString);
}
return temp;
}
}
set
{
lock (m_ExcludedFileExtensionsLocker)
{
m_ExcludedFileExtensions.Clear();
foreach (var extension in value)
{
temp.Add(extension);
}
return temp;
}
}
}
}
Для того, чтобы вернуть IEnumerable<Uri>
и IEnumerable<string>
, я выполнил копию string
с использованием метода string.Copy
. Но действительно ли нужно сделать эту копию? Я решил сделать копию string
s в соответствии со следующими соображениями: если свойства просто возвращают атрибут члена (то есть ссылку на этот атрибут), потоки читателей могут их изменить, поэтому я решил вернуть глубокую копию этих списков ,
Однако строки неизменяемы, поэтому нет необходимости делать копию этих списков путем копирования каждой строки и каждого uri из них? Другими словами, если я изменю свойство ExcludedFileExtensions
в приведенном выше примере, то может ли поток считывателя изменить исходный string
s в пределах переменной m_ExcludedFileExtensions
?
public IEnumerable<string> ExcludedFileExtensions
{
get
{
lock (m_ExcludedFileExtensionsLocker)
{
return new List<string>(m_ExcludedFileExtensions);
}
}
}