我已经编写了一个非常基本的同步集合,可以在桌面应用中使用。有没有办法比这更好/更容易?该集合需要由json.net直接序列化,显然需要进行同步。
此外,我想知道是否可以转换为未知的泛型类型来调用复制函数generic而不转换为接口。我认为这可能在一个大的列表上真的很慢,似乎不是必要的。
public class SynchronizedCollectionConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(SynchronizedCollection<>);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
// make list type from SynchronizedCollection generic type
var listType = typeof(List<>).MakeGenericType(objectType.GenericTypeArguments[0]);
// create instance of list type
var list = Activator.CreateInstance(listType);
// populate json to our list!
serializer.Populate(reader, list);
// create new SynchronizedCollection from populated list, easy! <3 json <3 c#
return Activator.CreateInstance(objectType, list);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
SynchronizedCollectionCopy collection = value as SynchronizedCollectionCopy;
// get a copy of the list synchronously
using (var waitTask = Task.Run<List<object>>(async () => { return await collection.Copy(); }))
{
// wait for synchronization.
waitTask.Wait();
// aaand serialize
serializer.Serialize(writer, waitTask.Result);
}
}
}
public interface SynchronizedCollectionCopy
{
Task<List<object>> Copy();
}
public class SynchronizedCollection<T> : IDisposable, SynchronizedCollectionCopy
{
private List<T> _storage;
private SemaphoreSlim _lock = new SemaphoreSlim(1, 1);
public int Count { get { return _storage.Count; } }
public SynchronizedCollection()
{
_storage = new List<T>();
}
public SynchronizedCollection(IEnumerable<T> items)
{
_storage = new List<T>(items);
}
public async Task Add(T item)
{
await _lock.WaitAsync();
try
{
_storage.Add(item);
}
catch
{
throw;
}
finally
{
_lock.Release();
}
}
public async Task Remove(Func<T, bool> predicate)
{
await _lock.WaitAsync();
try
{
T item;
while ((item = _storage.FirstOrDefault(predicate)) != null)
{
_storage.Remove(item);
}
}
catch
{
throw;
}
finally
{
_lock.Release();
}
}
public async Task Perform(Action<List<T>> actionOnList)
{
await _lock.WaitAsync();
try
{
actionOnList(_storage);
}
catch
{
throw;
}
finally
{
_lock.Release();
}
}
public async Task<List<object>> Copy()
{
await _lock.WaitAsync();
List<object> list = null;
try
{
list = new List<object>(_storage.Cast<object>());
}
catch
{
throw;
}
finally
{
_lock.Release();
}
return list;
}
public void Dispose()
{
_lock.Dispose();
}
}