我在线程之间有一个共享对象,用于保存文件状态信息。保存信息的对象是这个类:
/// <summary>
/// A synchronized dictionary class.
/// Uses ReaderWriterLockSlim to handle locking. The dictionary does not allow recursion by enumeration. It is purly used for quick read access.
/// </summary>
/// <typeparam name="T">Type that is going to be kept.</typeparam>
public sealed class SynchronizedDictionary<U,T> : IEnumerable<T>
{
private System.Threading.ReaderWriterLockSlim _lock = new System.Threading.ReaderWriterLockSlim();
private Dictionary<U, T> _collection = null;
public SynchronizedDictionary()
{
_collection = new Dictionary<U, T>();
}
/// <summary>
/// if getting:
/// Enters read lock.
/// Tries to get the value.
///
/// if setting:
/// Enters write lock.
/// Tries to set value.
/// </summary>
/// <param name="key">The key to fetch the value with.</param>
/// <returns>Object of T</returns>
public T this[U key]
{
get
{
_lock.EnterReadLock();
try
{
return _collection[key];
}
finally
{
_lock.ExitReadLock();
}
}
set
{
Add(key, value);
}
}
/// <summary>
/// Enters write lock.
/// Removes key from collection
/// </summary>
/// <param name="key">Key to remove.</param>
public void Remove(U key)
{
_lock.EnterWriteLock();
try
{
_collection.Remove(key);
}
finally
{
_lock.ExitWriteLock();
}
}
/// <summary>
/// Enters write lock.
/// Adds value to the collection if key does not exists.
/// </summary>
/// <param name="key">Key to add.</param>
/// <param name="value">Value to add.</param>
private void Add(U key, T value)
{
_lock.EnterWriteLock();
if (!_collection.ContainsKey(key))
{
try
{
_collection[key] = value;
}
finally
{
_lock.ExitWriteLock();
}
}
}
/// <summary>
/// Collection does not support iteration.
/// </summary>
/// <returns>Throw NotSupportedException</returns>
public IEnumerator<T> GetEnumerator()
{
throw new NotSupportedException();
}
/// <summary>
/// Collection does not support iteration.
/// </summary>
/// <returns>Throw NotSupportedException</returns>
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new NotSupportedException();
}
}
我这样称呼这本字典: SynchronizedDictionary _cache = new SynchronizedDictionary();
可以生成其他线程并像这样使用线程:_cache["key"];
字典可以在运行时修改。我认为这里没有问题。还是我错了?在我看来,问题在于枚举器,因为我想创建一个遍历集合的枚举器。我该怎么做呢?我想到了这三个解决方案:
- 像这样制作枚举器:http: //www.codeproject.com/Articles/56575/Thread-safe-enumeration-in-C (但使用 ReaderWriterLockSlim)
- 公开锁对象,就像 SyncRoot 一样(但使用 ReaderWriterLockSlim),因此调用者调用进入和退出读取方法。
- 改用数据库(SQLite fx)来保存信息。
数字 1) 的问题是:
- 它使用构造函数进入读取模式。如果手动调用 GetEnumerator() 而不使用 foreach 会怎样?忘记调用 dispose。
- 我不知道这是否是一种好的编码风格。尽管我喜欢代码。
- 如果调用者使用 foreach,我不知道调用者在枚举器的实例化和调用 dispose 之间可能会做什么。如果我理解了我正确阅读的文档,只要剩下一个读者做一些繁重的工作,这最终可能会阻止作者。
2)的问题是:
- 我不喜欢暴露这个。我知道 .NET API 可以做到这一点,但不喜欢它。
- 由调用者正确进入和退出
3)我的眼睛没有问题。但是我做这个小项目是作为一个业余项目,我想了解更多关于多线程和反射的知识,所以我想把它作为最后的选择。我想在运行时迭代集合的原因是我想找到符合某些条件的值。
也许只有我发明了一个问题?
我知道 ConcurrentDictionary,但我不想使用它。我将这个项目用作游乐场。玩线程和反射。
编辑
我被问到我在阅读和写作什么。我将在本次编辑中讲述这一点。我正在阅读和写作这门课:
public class AssemblyInformation
{
public string FilePath { get; private set; }
public string Name { get; private set; }
public AssemblyInformation(string filePath, string name)
{
FilePath = filePath;
Name = name;
}
}
我正在做很多读取,并且在运行时几乎没有写入。也许我会写 2000 和 1 篇。也不会有很多对象,也许是 200 个。