Compare commits

...

3 Commits

Author SHA1 Message Date
Diego
f531e4dfc5 10.6.19 2025-05-23 13:16:57 +08:00
Diego
8db9b32ba7 10.6.18 2025-05-23 12:55:21 +08:00
Diego
dd5691cbef 更新依赖 2025-05-22 14:40:56 +08:00
24 changed files with 518 additions and 83 deletions

View File

@@ -16,9 +16,9 @@ namespace ThingsGateway.Admin.Application;
/// 内存推送事件服务
/// </summary>
/// <typeparam name="TEntry"></typeparam>
public class EventService<TEntry> : IEventService<TEntry>
public class EventService<TEntry> : IEventService<TEntry>, IDisposable
{
private ConcurrentDictionary<string, Func<TEntry, Task>> Cache { get; } = new();
private ConcurrentDictionary<string, Func<TEntry, Task>> Cache = new();
public void Dispose()
{

View File

@@ -97,7 +97,7 @@ public class BlazorAppContext
AllResource = sysResources;
var ids = CurrentUser.ModuleList.Select(a => a.Id).ToHashSet();
CurrentUser.ModuleList = AllResource.Where(a => ids.Contains(a.Id)).OrderBy(a => a.SortCode).ToList();
AllMenus = sysResources.Where(a => a.Category == ResourceCategoryEnum.Menu);
AllMenus = AllResource.Where(a => a.Category == ResourceCategoryEnum.Menu);
if (moduleId == null)
{

View File

@@ -18,8 +18,6 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
using System.Diagnostics.CodeAnalysis;
using ThingsGateway.Admin.Application;
using ThingsGateway.Admin.Razor;
using ThingsGateway.Extension;

View File

@@ -1,7 +1,4 @@
using System.Buffers;
using System.Runtime.CompilerServices;
using ThingsGateway.NewLife.Collections;
using System.Runtime.CompilerServices;
namespace ThingsGateway.NewLife.Buffers;
@@ -83,7 +80,7 @@ internal sealed class BufferSegment : ReadOnlySequenceSegment<Byte>
}
else if (_array != null)
{
Pool.Shared.Return(_array);
ArrayPool<Byte>.Shared.Return(_array);
_array = null;
}
base.Memory = default;

View File

@@ -1,9 +1,4 @@
using System.Buffers;
using ThingsGateway.NewLife.Collections;
#if NETFRAMEWORK || NETSTANDARD2_0
#if NETFRAMEWORK || NETSTANDARD2_0
using ValueTask = System.Threading.Tasks.Task;
#endif
@@ -28,7 +23,7 @@ public sealed class PooledByteBufferWriter : IBufferWriter<Byte>, IDisposable
/// <param name="initialCapacity"></param>
public PooledByteBufferWriter(Int32 initialCapacity)
{
_rentedBuffer = Pool.Shared.Rent(initialCapacity);
_rentedBuffer = ArrayPool<Byte>.Shared.Rent(initialCapacity);
_index = 0;
}
@@ -45,7 +40,7 @@ public sealed class PooledByteBufferWriter : IBufferWriter<Byte>, IDisposable
/// <param name="initialCapacity"></param>
public void InitializeEmptyInstance(Int32 initialCapacity)
{
_rentedBuffer = Pool.Shared.Rent(initialCapacity);
_rentedBuffer = ArrayPool<Byte>.Shared.Rent(initialCapacity);
_index = 0;
}
@@ -63,7 +58,7 @@ public sealed class PooledByteBufferWriter : IBufferWriter<Byte>, IDisposable
var rentedBuffer = _rentedBuffer;
_rentedBuffer = null!;
Pool.Shared.Return(rentedBuffer);
ArrayPool<Byte>.Shared.Return(rentedBuffer);
}
/// <summary>通知 IBufferWriter已向输出写入 count 数据项。</summary>
@@ -119,11 +114,11 @@ public sealed class PooledByteBufferWriter : IBufferWriter<Byte>, IDisposable
}
}
var rentedBuffer = _rentedBuffer;
_rentedBuffer = Pool.Shared.Rent(num4);
_rentedBuffer = ArrayPool<Byte>.Shared.Rent(num4);
var span = rentedBuffer.AsSpan(0, _index);
span.CopyTo(_rentedBuffer);
span.Clear();
Pool.Shared.Return(rentedBuffer);
ArrayPool<Byte>.Shared.Return(rentedBuffer);
}
#endregion
}

View File

@@ -241,7 +241,7 @@ public static class SpanHelper
return;
}
var array = Pool.Shared.Rent(buffer.Length);
var array = ArrayPool<Byte>.Shared.Rent(buffer.Length);
try
{
@@ -251,7 +251,7 @@ public static class SpanHelper
}
finally
{
Pool.Shared.Return(array);
ArrayPool<Byte>.Shared.Return(array);
}
}
@@ -265,7 +265,7 @@ public static class SpanHelper
if (MemoryMarshal.TryGetArray(buffer, out var segment))
return stream.WriteAsync(segment.Array!, segment.Offset, segment.Count, cancellationToken);
var array = Pool.Shared.Rent(buffer.Length);
var array = ArrayPool<Byte>.Shared.Rent(buffer.Length);
buffer.Span.CopyTo(array);
var writeTask = stream.WriteAsync(array, 0, buffer.Length, cancellationToken);
@@ -277,7 +277,7 @@ public static class SpanHelper
}
finally
{
Pool.Shared.Return(array);
ArrayPool<Byte>.Shared.Return(array);
}
}, cancellationToken);
}

View File

@@ -1,5 +1,4 @@
using System.Buffers;
using System.Text;
using System.Text;
namespace ThingsGateway.NewLife.Collections;
@@ -95,7 +94,7 @@ public static class Pool
{
//if (ms == null) return null;
var buf = returnResult ? ms.ToArray() : Empty;
var buf = returnResult ? ms.ToArray() : Array.Empty<byte>();
Pool.MemoryStream.Return(ms);
@@ -133,11 +132,5 @@ public static class Pool
}
#endregion
#region ByteArray
/// <summary>字节数组共享存储</summary>
public static ArrayPool<Byte> Shared { get; set; } = ArrayPool<Byte>.Shared;
/// <summary>空数组</summary>
public static Byte[] Empty { get; } = [];
#endregion
}

View File

@@ -2,8 +2,6 @@
using System.Globalization;
using System.Reflection;
using ThingsGateway.NewLife.Collections;
namespace ThingsGateway.NewLife.Extension;
/// <summary>工具类</summary>
@@ -452,12 +450,12 @@ public class DefaultConvert
// 凑够8字节
if (buf.Length < 8)
{
var bts = Pool.Shared.Rent(8);
var bts = ArrayPool<Byte>.Shared.Rent(8);
Buffer.BlockCopy(buf, 0, bts, 0, buf.Length);
var dec = BitConverter.ToDouble(bts, 0).ToDecimal();
Pool.Shared.Return(bts);
ArrayPool<Byte>.Shared.Return(bts);
return dec;
}

View File

@@ -8,4 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
global using System.Buffers;
global using ThingsGateway.NewLife.Extension;

View File

@@ -5,7 +5,6 @@ using System.Net.Sockets;
using System.Runtime.InteropServices;
using ThingsGateway.NewLife.Caching;
using ThingsGateway.NewLife.Collections;
using ThingsGateway.NewLife.Net;
namespace ThingsGateway.NewLife;
@@ -52,7 +51,7 @@ public static class NetHelper
#endif
{
UInt32 dummy = 0;
var inOptionValues = Pool.Shared.Rent(Marshal.SizeOf(dummy) * 3);
var inOptionValues = ArrayPool<Byte>.Shared.Rent(Marshal.SizeOf(dummy) * 3);
// 是否启用Keep-Alive
BitConverter.GetBytes((UInt32)(isKeepAlive ? 1 : 0)).CopyTo(inOptionValues, 0);
@@ -63,7 +62,7 @@ public static class NetHelper
socket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
Pool.Shared.Return(inOptionValues);
ArrayPool<Byte>.Shared.Return(inOptionValues);
return;
}
@@ -538,11 +537,11 @@ public static class NetHelper
private static void Wake(String mac)
{
mac = mac.Replace("-", null).Replace(":", null);
var buffer = Pool.Shared.Rent(mac.Length / 2);
var buffer = ArrayPool<Byte>.Shared.Rent(mac.Length / 2);
for (var i = 0; i < buffer.Length; i++)
buffer[i] = Byte.Parse(mac.Substring(i * 2, 2), NumberStyles.HexNumber);
var bts = Pool.Shared.Rent(6 + 16 * buffer.Length);
var bts = ArrayPool<Byte>.Shared.Rent(6 + 16 * buffer.Length);
for (var i = 0; i < 6; i++)
bts[i] = 0xFF;
for (Int32 i = 6, k = 0; i < bts.Length; i++, k++)
@@ -560,8 +559,8 @@ public static class NetHelper
client.Close();
//client.SendAsync(bts, bts.Length, new IPEndPoint(IPAddress.Broadcast, 7));
Pool.Shared.Return(bts);
Pool.Shared.Return(buffer);
ArrayPool<Byte>.Shared.Return(bts);
ArrayPool<Byte>.Shared.Return(buffer);
}
#endregion

View File

@@ -1,7 +1,6 @@
using System.Reflection;
using System.Runtime.InteropServices;
using ThingsGateway.NewLife.Collections;
using ThingsGateway.NewLife.Reflection;
namespace ThingsGateway.NewLife.Serialization;
@@ -156,7 +155,7 @@ public class Binary : FormatterBase, IBinary
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
Stream.Write(buffer);
#else
var array = Pool.Shared.Rent(buffer.Length);
var array = ArrayPool<Byte>.Shared.Rent(buffer.Length);
try
{
buffer.CopyTo(array);
@@ -165,7 +164,7 @@ public class Binary : FormatterBase, IBinary
}
finally
{
Pool.Shared.Return(array);
ArrayPool<Byte>.Shared.Return(array);
}
#endif
}
@@ -494,7 +493,7 @@ public class Binary : FormatterBase, IBinary
/// <param name="max"></param>
public void WriteBCD(String value, Int32 max)
{
var buf = Pool.Shared.Rent(max);
var buf = ArrayPool<Byte>.Shared.Rent(max);
for (Int32 i = 0, j = 0; i < max && j + 1 < value.Length; i++, j += 2)
{
var a = (Byte)(value[j] - '0');
@@ -503,7 +502,7 @@ public class Binary : FormatterBase, IBinary
}
Write(buf, 0, max);
Pool.Shared.Return(buf);
ArrayPool<Byte>.Shared.Return(buf);
}
/// <summary>写入定长字符串。多余截取,少则补零</summary>
@@ -511,11 +510,11 @@ public class Binary : FormatterBase, IBinary
/// <param name="max"></param>
public void WriteFixedString(String? value, Int32 max)
{
var buf = Pool.Shared.Rent(max);
var buf = ArrayPool<Byte>.Shared.Rent(max);
if (!value.IsNullOrEmpty()) Encoding.GetBytes(value, 0, value.Length, buf, 0);
Write(buf, 0, max);
Pool.Shared.Return(buf);
ArrayPool<Byte>.Shared.Return(buf);
}
/// <summary>读取定长字符串。多余截取,少则补零</summary>

View File

@@ -1,7 +1,6 @@
using System.Globalization;
using System.Xml;
using ThingsGateway.NewLife.Collections;
using ThingsGateway.NewLife.Reflection;
namespace ThingsGateway.NewLife.Serialization;
@@ -144,10 +143,10 @@ public class XmlGeneral : XmlHandlerBase
else if (type == typeof(Byte[]))
{
// 用字符串长度作为预设缓冲区的长度
var buf = Pool.Shared.Rent(reader.Value.Length);
var buf = ArrayPool<Byte>.Shared.Rent(reader.Value.Length);
var count = reader.ReadContentAsBase64(buf, 0, buf.Length);
value = buf.ReadBytes(0, count);
Pool.Shared.Return(buf);
ArrayPool<Byte>.Shared.Return(buf);
return true;
}

View File

@@ -24,9 +24,8 @@ public static class ParallelExtensions
/// <param name="body">要执行的操作</param>
public static void ParallelForEach<T>(this IEnumerable<T> source, Action<T> body)
{
// 创建并行操作的选项对象,设置最大并行度为当前处理器数量的一半
ParallelOptions options = new();
options.MaxDegreeOfParallelism = Environment.ProcessorCount / 2 == 0 ? 1 : Environment.ProcessorCount / 2;
options.MaxDegreeOfParallelism = Environment.ProcessorCount;
// 使用 Parallel.ForEach 执行指定的操作
Parallel.ForEach(source, options, (variable) =>
{
@@ -42,9 +41,8 @@ public static class ParallelExtensions
/// <param name="body">要执行的操作</param>
public static void ParallelForEach<T>(this IEnumerable<T> source, Action<T, ParallelLoopState, long> body)
{
// 创建并行操作的选项对象,设置最大并行度为当前处理器数量的一半
ParallelOptions options = new();
options.MaxDegreeOfParallelism = Environment.ProcessorCount / 2 == 0 ? 1 : Environment.ProcessorCount / 2;
options.MaxDegreeOfParallelism = Environment.ProcessorCount;
// 使用 Parallel.ForEach 执行指定的操作
Parallel.ForEach(source, options, (variable, state, index) =>
{

View File

@@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BootstrapBlazor.FontAwesome" Version="9.0.2" />
<PackageReference Include="BootstrapBlazor" Version="9.6.3" />
<PackageReference Include="BootstrapBlazor" Version="9.6.4" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
</ItemGroup>

View File

@@ -1,8 +1,8 @@
<Project>
<PropertyGroup>
<PluginVersion>10.6.16</PluginVersion>
<ProPluginVersion>10.6.16</ProPluginVersion>
<PluginVersion>10.6.19</PluginVersion>
<ProPluginVersion>10.6.19</ProPluginVersion>
<AuthenticationVersion>2.1.7</AuthenticationVersion>
</PropertyGroup>

View File

@@ -0,0 +1,464 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
//------------------------------------------------------------------------------
using System.Collections;
namespace ThingsGateway.Gateway.Application;
public class ThreadSafeStringDictionary<T> : IDictionary<string, T>, IReadOnlyDictionary<string, T>
{
private const int DEFAULT_PARTITIONS = 128;
private readonly Dictionary<string, T>[] _partitions;
private readonly object[] _partitionLocks;
private readonly IEqualityComparer<string> _comparer;
public ThreadSafeStringDictionary() : this(DEFAULT_PARTITIONS, null) { }
public ThreadSafeStringDictionary(int partitionCount, IEqualityComparer<string> comparer)
{
if (partitionCount < 1)
throw new ArgumentOutOfRangeException(nameof(partitionCount));
_partitions = new Dictionary<string, T>[partitionCount];
_partitionLocks = new object[partitionCount];
_comparer = comparer ?? StringComparer.Ordinal;
for (int i = 0; i < partitionCount; i++)
{
_partitions[i] = new Dictionary<string, T>(_comparer);
_partitionLocks[i] = new object();
}
}
private int GetPartitionIndex(string key)
{
if (key == null) throw new ArgumentNullException(nameof(key));
return Math.Abs(_comparer.GetHashCode(key)) % _partitions.Length;
}
// 基本操作
public T this[string key]
{
get
{
int index = GetPartitionIndex(key);
lock (_partitionLocks[index])
{
return _partitions[index][key];
}
}
set
{
int index = GetPartitionIndex(key);
lock (_partitionLocks[index])
{
_partitions[index][key] = value;
}
}
}
public ICollection<string> Keys => GetAllItems().Select(kv => kv.Key).ToList();
public ICollection<T> Values => GetAllItems().Select(kv => kv.Value).ToList();
public int Count
{
get
{
int count = 0;
for (int i = 0; i < _partitions.Length; i++)
{
lock (_partitionLocks[i])
{
count += _partitions[i].Count;
}
}
return count;
}
}
public bool IsReadOnly => false;
IEnumerable<string> IReadOnlyDictionary<string, T>.Keys => Keys;
IEnumerable<T> IReadOnlyDictionary<string, T>.Values => Values;
public void Add(string key, T value)
{
int index = GetPartitionIndex(key);
lock (_partitionLocks[index])
{
_partitions[index].Add(key, value);
}
}
public void Add(KeyValuePair<string, T> item) => Add(item.Key, item.Value);
public void Clear()
{
for (int i = 0; i < _partitions.Length; i++)
{
lock (_partitionLocks[i])
{
_partitions[i].Clear();
}
}
}
public bool Contains(KeyValuePair<string, T> item)
{
int index = GetPartitionIndex(item.Key);
lock (_partitionLocks[index])
{
return _partitions[index].TryGetValue(item.Key, out var value) &&
EqualityComparer<T>.Default.Equals(value, item.Value);
}
}
public bool ContainsKey(string key)
{
int index = GetPartitionIndex(key);
lock (_partitionLocks[index])
{
return _partitions[index].ContainsKey(key);
}
}
public bool Remove(string key)
{
int index = GetPartitionIndex(key);
lock (_partitionLocks[index])
{
return _partitions[index].Remove(key);
}
}
public bool Remove(KeyValuePair<string, T> item)
{
int index = GetPartitionIndex(item.Key);
lock (_partitionLocks[index])
{
if (_partitions[index].TryGetValue(item.Key, out var value) &&
EqualityComparer<T>.Default.Equals(value, item.Value))
{
return _partitions[index].Remove(item.Key);
}
return false;
}
}
public bool TryGetValue(string key, out T value)
{
int index = GetPartitionIndex(key);
lock (_partitionLocks[index])
{
return _partitions[index].TryGetValue(key, out value);
}
}
public void CopyTo(KeyValuePair<string, T>[] array, int arrayIndex)
{
if (array == null) throw new ArgumentNullException(nameof(array));
if (arrayIndex < 0) throw new ArgumentOutOfRangeException(nameof(arrayIndex));
if (array.Length - arrayIndex < Count) throw new ArgumentException("Target array too small");
foreach (var item in GetAllItems())
{
array[arrayIndex++] = item;
}
}
// 枚举器实现
public IEnumerator<KeyValuePair<string, T>> GetEnumerator()
{
return GetAllItems().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public void AddRange(IEnumerable<KeyValuePair<string, T>> items)
{
var grouped = items.GroupBy(item => GetPartitionIndex(item.Key));
foreach (var group in grouped)
{
lock (_partitionLocks[group.Key])
{
foreach (var item in group)
{
_partitions[group.Key][item.Key] = item.Value;
}
}
}
}
public Dictionary<string, T> GetSnapshot()
{
var snapshot = new Dictionary<string, T>(_comparer);
for (int i = 0; i < _partitions.Length; i++)
{
lock (_partitionLocks[i])
{
foreach (var kvp in _partitions[i])
{
snapshot[kvp.Key] = kvp.Value;
}
}
}
return snapshot;
}
private IEnumerable<KeyValuePair<string, T>> GetAllItems()
{
for (int i = 0; i < _partitions.Length; i++)
{
lock (_partitionLocks[i])
{
foreach (var item in _partitions[i]) // 直接枚举原字典
{
yield return item;
}
}
}
}
}
public class ThreadSafeLongDictionary<T> : IDictionary<long, T>, IReadOnlyDictionary<long, T>
{
private const int DEFAULT_PARTITIONS = 128;
private readonly Dictionary<long, T>[] _partitions;
private readonly object[] _partitionLocks;
public ThreadSafeLongDictionary() : this(DEFAULT_PARTITIONS) { }
public ThreadSafeLongDictionary(int partitionCount)
{
if (partitionCount < 1)
throw new ArgumentOutOfRangeException(nameof(partitionCount));
_partitions = new Dictionary<long, T>[partitionCount];
_partitionLocks = new object[partitionCount];
for (int i = 0; i < partitionCount; i++)
{
_partitions[i] = new Dictionary<long, T>();
_partitionLocks[i] = new object();
}
}
private int GetPartitionIndex(long key)
{
// 使用混合哈希算法减少碰撞
uint hash = (uint)key;
hash = ((hash >> 16) ^ hash) * 0x45d9f3b;
hash = ((hash >> 16) ^ hash) * 0x45d9f3b;
hash = (hash >> 16) ^ hash;
return (int)(hash % _partitions.Length);
}
public T this[long key]
{
get
{
int index = GetPartitionIndex(key);
lock (_partitionLocks[index])
{
return _partitions[index][key];
}
}
set
{
int index = GetPartitionIndex(key);
lock (_partitionLocks[index])
{
_partitions[index][key] = value;
}
}
}
public ICollection<long> Keys => GetAllItems().Select(kv => kv.Key).ToList();
public ICollection<T> Values => GetAllItems().Select(kv => kv.Value).ToList();
public int Count
{
get
{
int count = 0;
for (int i = 0; i < _partitions.Length; i++)
{
lock (_partitionLocks[i])
{
count += _partitions[i].Count;
}
}
return count;
}
}
public bool IsReadOnly => false;
IEnumerable<long> IReadOnlyDictionary<long, T>.Keys => Keys;
IEnumerable<T> IReadOnlyDictionary<long, T>.Values => Values;
public void Add(long key, T value)
{
int index = GetPartitionIndex(key);
lock (_partitionLocks[index])
{
_partitions[index].Add(key, value);
}
}
public void Add(KeyValuePair<long, T> item) => Add(item.Key, item.Value);
public void Clear()
{
for (int i = 0; i < _partitions.Length; i++)
{
lock (_partitionLocks[i])
{
_partitions[i].Clear();
}
}
}
public bool Contains(KeyValuePair<long, T> item)
{
int index = GetPartitionIndex(item.Key);
lock (_partitionLocks[index])
{
return _partitions[index].TryGetValue(item.Key, out var value) &&
EqualityComparer<T>.Default.Equals(value, item.Value);
}
}
public bool ContainsKey(long key)
{
int index = GetPartitionIndex(key);
lock (_partitionLocks[index])
{
return _partitions[index].ContainsKey(key);
}
}
public bool Remove(long key)
{
int index = GetPartitionIndex(key);
lock (_partitionLocks[index])
{
return _partitions[index].Remove(key);
}
}
public bool Remove(KeyValuePair<long, T> item)
{
int index = GetPartitionIndex(item.Key);
lock (_partitionLocks[index])
{
if (_partitions[index].TryGetValue(item.Key, out var value) &&
EqualityComparer<T>.Default.Equals(value, item.Value))
{
return _partitions[index].Remove(item.Key);
}
return false;
}
}
public bool TryGetValue(long key, out T value)
{
int index = GetPartitionIndex(key);
lock (_partitionLocks[index])
{
return _partitions[index].TryGetValue(key, out value);
}
}
public void CopyTo(KeyValuePair<long, T>[] array, int arrayIndex)
{
if (array == null) throw new ArgumentNullException(nameof(array));
if (arrayIndex < 0) throw new ArgumentOutOfRangeException(nameof(arrayIndex));
if (array.Length - arrayIndex < Count) throw new ArgumentException("Target array too small");
foreach (var item in GetAllItems())
{
array[arrayIndex++] = item;
}
}
public IEnumerator<KeyValuePair<long, T>> GetEnumerator()
{
return GetAllItems().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public void AddRange(IEnumerable<KeyValuePair<long, T>> items)
{
var grouped = items.GroupBy(item => GetPartitionIndex(item.Key));
foreach (var group in grouped)
{
lock (_partitionLocks[group.Key])
{
foreach (var item in group)
{
_partitions[group.Key][item.Key] = item.Value;
}
}
}
}
public Dictionary<long, T> GetSnapshot()
{
var snapshot = new Dictionary<long, T>();
for (int i = 0; i < _partitions.Length; i++)
{
lock (_partitionLocks[i])
{
foreach (var kvp in _partitions[i])
{
snapshot[kvp.Key] = kvp.Value;
}
}
}
return snapshot;
}
private IEnumerable<KeyValuePair<long, T>> GetAllItems()
{
for (int i = 0; i < _partitions.Length; i++)
{
lock (_partitionLocks[i])
{
foreach (var item in _partitions[i])
{
yield return item;
}
}
}
}
public string GetPartitionStats()
{
var stats = new System.Text.StringBuilder();
for (int i = 0; i < _partitions.Length; i++)
{
lock (_partitionLocks[i])
{
stats.AppendLine($"Partition {i}: {_partitions[i].Count} items");
}
}
return stats.ToString();
}
}

View File

@@ -17,6 +17,7 @@ using Newtonsoft.Json.Linq;
using SqlSugar;
using ThingsGateway.Gateway.Application.Extensions;
using ThingsGateway.NewLife.Extension;
using ThingsGateway.NewLife.Json.Extension;
namespace ThingsGateway.Gateway.Application;
@@ -34,10 +35,6 @@ public class VariableRuntime : Variable, IVariable, IDisposable
private bool? _isOnlineChanged;
protected object? _value;
public VariableRuntime()
{
}
/// <summary>
/// 变化时间
/// </summary>
@@ -343,7 +340,7 @@ public class VariableRuntime : Variable, IVariable, IDisposable
public void Init(DeviceRuntime deviceRuntime)
{
GlobalData.AlarmEnableIdVariables.TryRemove(Id, out _);
GlobalData.AlarmEnableIdVariables.Remove(Id);
if (GlobalData.RealAlarmIdVariables.TryRemove(Id, out var oldAlarm))
{
oldAlarm.EventType = EventTypeEnum.Finish;
@@ -352,12 +349,12 @@ public class VariableRuntime : Variable, IVariable, IDisposable
}
DeviceRuntime?.VariableRuntimes?.TryRemove(Name, out _);
DeviceRuntime?.VariableRuntimes?.Remove(Name);
DeviceRuntime = deviceRuntime;
DeviceRuntime?.VariableRuntimes?.TryAdd(Name, this);
GlobalData.IdVariables.TryRemove(Id, out _);
GlobalData.IdVariables.Remove(Id);
GlobalData.IdVariables.TryAdd(Id, this);
if (AlarmEnable)
{
@@ -369,11 +366,11 @@ public class VariableRuntime : Variable, IVariable, IDisposable
public void Dispose()
{
DeviceRuntime?.VariableRuntimes?.TryRemove(Name, out _);
DeviceRuntime?.VariableRuntimes?.Remove(Name);
GlobalData.IdVariables.TryRemove(Id, out _);
GlobalData.IdVariables.Remove(Id);
GlobalData.AlarmEnableIdVariables.TryRemove(Id, out _);
GlobalData.AlarmEnableIdVariables.Remove(Id);
if (GlobalData.RealAlarmIdVariables.TryRemove(Id, out var oldAlarm))
{
oldAlarm.EventType = EventTypeEnum.Finish;

View File

@@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj" />
<PackageReference Include="BootstrapBlazor.UniverSheet" Version="9.0.4" />
<PackageReference Include="BootstrapBlazor.UniverSheet" Version="9.0.5" />
<PackageReference Include="BootstrapBlazor.WinBox" Version="9.0.7" />
<PackageReference Include="BootstrapBlazor.CodeEditor" Version="9.0.1" />
<ProjectReference Include="..\..\Admin\ThingsGateway.Admin.Razor\ThingsGateway.Admin.Razor.csproj" />

View File

@@ -30,6 +30,7 @@ public partial class RulesPage
}
protected override async ValueTask DisposeAsync(bool disposing)
{
RulesDispatchService.UnSubscribe(Notify);
if (Module != null)
{
await Module.InvokeVoidAsync("disposeJS", DiagramsJS);
@@ -155,10 +156,6 @@ public partial class RulesPage
[NotNull]
private IDispatchService<Rules>? RulesDispatchService { get; set; }
public void Dispose()
{
RulesDispatchService.UnSubscribe(Notify);
}
private ExecutionContext? context;
protected override async Task OnInitializedAsync()

View File

@@ -19,7 +19,7 @@
<PackageReference Include="SqlSugar.TDengineCore" Version="4.18.31" GeneratePathProperty="true">
<PackageReference Include="SqlSugar.TDengineCore" Version="4.18.32" GeneratePathProperty="true">
<PrivateAssets>contentFiles;compile;build;buildMultitargeting;buildTransitive;analyzers;</PrivateAssets>
</PackageReference>

View File

@@ -19,8 +19,6 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
using System.Diagnostics.CodeAnalysis;
using ThingsGateway.Admin.Application;
using ThingsGateway.Admin.Razor;
using ThingsGateway.Extension;

View File

@@ -51,6 +51,9 @@
<!--动态适用GC-->
<GarbageCollectionAdaptationMode>1</GarbageCollectionAdaptationMode>
<!--<TieredCompilation>false</TieredCompilation>-->
<!--使用自托管线程池-->
<!--<UseWindowsThreadPool>false</UseWindowsThreadPool> -->

View File

@@ -18,8 +18,6 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
using System.Diagnostics.CodeAnalysis;
using ThingsGateway.Admin.Application;
using ThingsGateway.Admin.Razor;
using ThingsGateway.Extension;

View File

@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>10.6.16</Version>
<Version>10.6.19</Version>
</PropertyGroup>
<ItemGroup>