mirror of
https://github.com/evopro-ag/Sharp7Reactive.git
synced 2026-02-04 07:42:53 +00:00
Fix multithreadign issue with lingering subscriptions
This commit is contained in:
@@ -53,10 +53,13 @@ internal class ConcurrentSubjectDictionary<TKey, TValue> : IDisposable
|
|||||||
{
|
{
|
||||||
lock (dictionaryLock)
|
lock (dictionaryLock)
|
||||||
{
|
{
|
||||||
var subject = dictionary.AddOrUpdate(key, k => new SubjectWithRefCounter {Counter = 1, Subject = CreateSubject(k)}, (key1, counter) =>
|
var subject = dictionary.AddOrUpdate(
|
||||||
|
key,
|
||||||
|
k => new SubjectWithRefCounter(CreateSubject(k)),
|
||||||
|
(_, subjectWithRefCounter) =>
|
||||||
{
|
{
|
||||||
counter.Counter = counter.Counter + 1;
|
subjectWithRefCounter.IncreaseCount();
|
||||||
return counter;
|
return subjectWithRefCounter;
|
||||||
});
|
});
|
||||||
|
|
||||||
return new DisposableItem<TValue>(subject.Subject.AsObservable(), () => RemoveIfNoLongerInUse(key));
|
return new DisposableItem<TValue>(subject.Subject.AsObservable(), () => RemoveIfNoLongerInUse(key));
|
||||||
@@ -65,8 +68,7 @@ internal class ConcurrentSubjectDictionary<TKey, TValue> : IDisposable
|
|||||||
|
|
||||||
public bool TryGetObserver(TKey key, out IObserver<TValue> subject)
|
public bool TryGetObserver(TKey key, out IObserver<TValue> subject)
|
||||||
{
|
{
|
||||||
SubjectWithRefCounter subjectWithRefCount;
|
if (dictionary.TryGetValue(key, out var subjectWithRefCount))
|
||||||
if (dictionary.TryGetValue(key, out subjectWithRefCount))
|
|
||||||
{
|
{
|
||||||
subject = subjectWithRefCount.Subject.AsObserver();
|
subject = subjectWithRefCount.Subject.AsObserver();
|
||||||
return true;
|
return true;
|
||||||
@@ -101,15 +103,9 @@ internal class ConcurrentSubjectDictionary<TKey, TValue> : IDisposable
|
|||||||
private void RemoveIfNoLongerInUse(TKey variableName)
|
private void RemoveIfNoLongerInUse(TKey variableName)
|
||||||
{
|
{
|
||||||
lock (dictionaryLock)
|
lock (dictionaryLock)
|
||||||
{
|
if (dictionary.TryGetValue(variableName, out var subjectWithRefCount))
|
||||||
SubjectWithRefCounter subjectWithRefCount;
|
if (subjectWithRefCount.DecreaseCount() < 1)
|
||||||
if (dictionary.TryGetValue(variableName, out subjectWithRefCount))
|
dictionary.TryRemove(variableName, out _);
|
||||||
{
|
|
||||||
if (subjectWithRefCount.Counter == 1)
|
|
||||||
dictionary.TryRemove(variableName, out subjectWithRefCount);
|
|
||||||
else subjectWithRefCount.Counter--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~ConcurrentSubjectDictionary()
|
~ConcurrentSubjectDictionary()
|
||||||
@@ -119,7 +115,16 @@ internal class ConcurrentSubjectDictionary<TKey, TValue> : IDisposable
|
|||||||
|
|
||||||
class SubjectWithRefCounter
|
class SubjectWithRefCounter
|
||||||
{
|
{
|
||||||
public int Counter { get; set; }
|
private int counter = 1;
|
||||||
public ISubject<TValue> Subject { get; set; }
|
|
||||||
|
public SubjectWithRefCounter(ISubject<TValue> subject)
|
||||||
|
{
|
||||||
|
Subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ISubject<TValue> Subject { get; }
|
||||||
|
|
||||||
|
public int DecreaseCount() => Interlocked.Decrement(ref counter);
|
||||||
|
public int IncreaseCount() => Interlocked.Increment(ref counter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,5 +17,5 @@ internal interface IS7Connector : IDisposable
|
|||||||
Task WriteBit(Operand operand, ushort startByteAddress, byte bitAdress, bool value, ushort dbNo, CancellationToken token);
|
Task WriteBit(Operand operand, ushort startByteAddress, byte bitAdress, bool value, ushort dbNo, CancellationToken token);
|
||||||
Task WriteBytes(Operand operand, ushort startByteAddress, byte[] data, ushort dbNo, CancellationToken token);
|
Task WriteBytes(Operand operand, ushort startByteAddress, byte[] data, ushort dbNo, CancellationToken token);
|
||||||
|
|
||||||
Task<Dictionary<string, byte[]>> ExecuteMultiVarRequest(IReadOnlyList<string> variableNames);
|
Task<IReadOnlyDictionary<string, byte[]>> ExecuteMultiVarRequest(IReadOnlyList<string> variableNames);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ internal class Sharp7Connector : IS7Connector
|
|||||||
await CloseConnection();
|
await CloseConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Dictionary<string, byte[]>> ExecuteMultiVarRequest(IReadOnlyList<string> variableNames)
|
public async Task<IReadOnlyDictionary<string, byte[]>> ExecuteMultiVarRequest(IReadOnlyList<string> variableNames)
|
||||||
{
|
{
|
||||||
if (variableNames.IsEmpty())
|
if (variableNames.IsEmpty())
|
||||||
return new Dictionary<string, byte[]>();
|
return new Dictionary<string, byte[]>();
|
||||||
|
|||||||
Reference in New Issue
Block a user