diff --git a/Cis.Application/Cis.Application.xml b/Cis.Application/Cis.Application.xml index 40d6810..0910e50 100644 --- a/Cis.Application/Cis.Application.xml +++ b/Cis.Application/Cis.Application.xml @@ -606,6 +606,13 @@ + + + 获取标签计算结果列表 + + + + 激活相机进入运算 @@ -658,6 +665,13 @@ + + + 获取标签计算结果列表 + + + + 追踪标签服务类 @@ -673,6 +687,11 @@ MarkSearcherDict 原子操作锁 + + + MarkSearcherDict 中 MarkLabel 原子操作锁 + + ActivateSearcher 原子操作 @@ -687,6 +706,22 @@ + + + ActivateMarkLabel 原子操作 + + + + + + + + DeactivateMarkLabel 原子操作 + + + + + 当前相机计算参数 @@ -699,7 +734,12 @@ - {cameraId, MarkLabelCalcParams} + {markLabelId, MarkLabelCalcParams} + + + + + {markLabelId, MarkLabelCalcParams} @@ -792,6 +832,12 @@ + + + 更新相机计算参数 + + + 配置应用所需服务,在该方法中可以添加应用所需要的功能或服务 diff --git a/Cis.Application/Core/Center/CameraDataCenter.cs b/Cis.Application/Core/Center/CameraDataCenter.cs index 3a21605..4b1db50 100644 --- a/Cis.Application/Core/Center/CameraDataCenter.cs +++ b/Cis.Application/Core/Center/CameraDataCenter.cs @@ -63,20 +63,20 @@ public class CameraDataCenter : ISingleton // 启动 CameraPtzThread RefreshCameraPtzThread.Start(); - //// 初始化 MarkSearcherThread - //RefreshMarkSearcherThread = new Thread(async () => - //{ - // while (true) - // { - // await RefreshMarkSearchers(); - // Thread.Sleep(_options.MarkSearcher.LoopInterval); - // } - //}) - //{ - // IsBackground = true// 设置后台线程 - //}; - //// 启动 MarkSearcherThread - //RefreshMarkSearcherThread.Start(); + // 初始化 MarkSearcherThread + RefreshMarkSearcherThread = new Thread(async () => + { + while (true) + { + await RefreshMarkSearchers(); + Thread.Sleep(_options.MarkSearcher.LoopInterval); + } + }) + { + IsBackground = true// 设置后台线程 + }; + // 启动 MarkSearcherThread + RefreshMarkSearcherThread.Start(); } /// @@ -135,32 +135,8 @@ public class CameraDataCenter : ISingleton if (string.IsNullOrEmpty(ptzInfoStr)) return; PtzInfo ptzInfo = ptzInfoStr.ToObject(); if (ptzInfo == null) return; - markSearcher.UpdateCameraCalcParams(ptzInfo); - List resultList = await markSearcher.SearchAsync(); - SearchResultListDict[cameraId] = resultList; + await markSearcher.UpdateCameraCalcParamsAsync(ptzInfo); } #endregion Loop - - #region Base Method - - public List GetMarkLabelCalcResultList(long cameraId) - { - bool ret = SearchResultListDict.TryGetValue(cameraId, out List resultList); - return ret ? resultList : new List(); - } - - #endregion Base Method - - #region Base Method Async - - public async Task> GetMarkLabelCalcResultListAsync(long cameraId) - { - return await Task.Run(() => - { - return GetMarkLabelCalcResultList(cameraId); - }); - } - - #endregion Base Method Async } \ No newline at end of file diff --git a/Cis.Application/Core/Component/MarkSeacher/IMarkSearcherServer.cs b/Cis.Application/Core/Component/MarkSeacher/IMarkSearcherServer.cs index 9c63f74..2fa7250 100644 --- a/Cis.Application/Core/Component/MarkSeacher/IMarkSearcherServer.cs +++ b/Cis.Application/Core/Component/MarkSeacher/IMarkSearcherServer.cs @@ -59,9 +59,16 @@ public interface IMarkSearcherServer /// public bool IsExistsMarkLabel(long cameraId, long markLabelId); + /// + /// 获取标签计算结果列表 + /// + /// + /// + public List GetMarkLabelCalcResultList(long cameraId); + #endregion Base Method - #region Base Method + #region Base Method Async /// /// 激活相机进入运算 @@ -115,5 +122,12 @@ public interface IMarkSearcherServer /// public Task IsExistsMarkLabelAsync(long cameraId, long markLabelId); - #endregion Base Method + /// + /// 获取标签计算结果列表 + /// + /// + /// + public Task> GetMarkLabelCalcResultListAsync(long cameraId); + + #endregion Base Method Async } \ No newline at end of file diff --git a/Cis.Application/Core/Component/MarkSeacher/MarkSearcherServer.cs b/Cis.Application/Core/Component/MarkSeacher/MarkSearcherServer.cs index 5c6db29..61823c9 100644 --- a/Cis.Application/Core/Component/MarkSeacher/MarkSearcherServer.cs +++ b/Cis.Application/Core/Component/MarkSeacher/MarkSearcherServer.cs @@ -31,6 +31,11 @@ public class MarkSearcherServer : IMarkSearcherServer, ISingleton /// private ReaderWriterLockSlim MsDictRWLock { get; } = new(); + /// + /// MarkSearcherDict 中 MarkLabel 原子操作锁 + /// + private ReaderWriterLockSlim MsMlRWLock { get; } = new(); + #endregion Attr public MarkSearcherServer( @@ -51,7 +56,7 @@ public class MarkSearcherServer : IMarkSearcherServer, ISingleton { try { - MsDictRWLock.EnterWriteLock(); + MsDictRWLock.TryEnterWriteLock(2000); return ActivateSearcherAtom(cameraId); } finally @@ -126,7 +131,7 @@ public class MarkSearcherServer : IMarkSearcherServer, ISingleton { try { - MsDictRWLock.EnterWriteLock(); + MsDictRWLock.TryEnterWriteLock(2000); return DeactivateSearcherAtom(cameraId); } finally @@ -170,6 +175,25 @@ public class MarkSearcherServer : IMarkSearcherServer, ISingleton } public bool ActivateMarkLabel(long cameraId, long markLabelId) + { + try + { + MsMlRWLock.TryEnterWriteLock(2000); + return ActivateMarkLabelAtom(cameraId, markLabelId); + } + finally + { + MsMlRWLock.ExitWriteLock(); + } + } + + /// + /// ActivateMarkLabel 原子操作 + /// + /// + /// + /// + private bool ActivateMarkLabelAtom(long cameraId, long markLabelId) { bool ret = MarkSearcherDict.TryGetValue(cameraId, out MarkSearcherBase markSearcher); if (!ret) return false; @@ -190,6 +214,25 @@ public class MarkSearcherServer : IMarkSearcherServer, ISingleton } public bool DeactivateMarkLabel(long cameraId, long markLabelId) + { + try + { + MsMlRWLock.TryEnterWriteLock(2000); + return DeactivateMarkLabelAtom(cameraId, markLabelId); + } + finally + { + MsMlRWLock.ExitWriteLock(); + } + } + + /// + /// DeactivateMarkLabel 原子操作 + /// + /// + /// + /// + private bool DeactivateMarkLabelAtom(long cameraId, long markLabelId) { bool ret = MarkSearcherDict.TryGetValue(cameraId, out MarkSearcherBase markSearcher); if (!ret) return false; @@ -203,64 +246,54 @@ public class MarkSearcherServer : IMarkSearcherServer, ISingleton && searcher.IsExistsMarkLabelCalcParams(markLabelId); } + public List GetMarkLabelCalcResultList(long cameraId) + { + bool ret = MarkSearcherDict.TryGetValue(cameraId, out MarkSearcherBase markSearcher); + return ret ? markSearcher.GetMarkLabelCalcResultList() : new List(); + } + #endregion Base Method #region Base Method Async public async Task ActivateSearcherAsync(long cameraId) { - return await Task.Run(() => - { - return ActivateSearcher(cameraId); - }); + return await Task.Run(() => ActivateSearcher(cameraId)); } public async Task DeactivateSearcherAsync(long cameraId) { - return await Task.Run(() => - { - return DeactivateSearcher(cameraId); - }); + return await Task.Run(() => DeactivateSearcher(cameraId)); } public async Task IsExistsSearcherAsync(long cameraId) { - return await Task.Run(() => - { - return IsExistsSearcher(cameraId); - }); + return await Task.Run(() => IsExistsSearcher(cameraId)); } public async Task GetSearcherAsync(long cameraId) { - return await Task.Run(() => - { - return GetSearcher(cameraId); - }); + return await Task.Run(() => GetSearcher(cameraId)); } public async Task ActivateMarkLabelAsync(long cameraId, long markLabelId) { - return await Task.Run(() => - { - return ActivateMarkLabel(cameraId, markLabelId); - }); + return await Task.Run(() => ActivateMarkLabel(cameraId, markLabelId)); } public async Task DeactivateMarkLabelAsync(long cameraId, long markLabelId) { - return await Task.Run(() => - { - return DeactivateMarkLabel(cameraId, markLabelId); - }); + return await Task.Run(() => DeactivateMarkLabel(cameraId, markLabelId)); } public async Task IsExistsMarkLabelAsync(long cameraId, long markLabelId) { - return await Task.Run(() => - { - return IsExistsMarkLabel(cameraId, markLabelId); - }); + return await Task.Run(() => IsExistsMarkLabel(cameraId, markLabelId)); + } + + public async Task> GetMarkLabelCalcResultListAsync(long cameraId) + { + return await Task.Run(() => GetMarkLabelCalcResultList(cameraId)); } #endregion Base Method Async diff --git a/Cis.Application/Core/Component/MarkSeacher/Seacher/MarkSearcherBase.cs b/Cis.Application/Core/Component/MarkSeacher/Seacher/MarkSearcherBase.cs index 5ea5cee..40ff977 100644 --- a/Cis.Application/Core/Component/MarkSeacher/Seacher/MarkSearcherBase.cs +++ b/Cis.Application/Core/Component/MarkSeacher/Seacher/MarkSearcherBase.cs @@ -21,9 +21,14 @@ public abstract class MarkSearcherBase protected Matrix World2CameraMatrix { get; set; } /// - /// {cameraId, MarkLabelCalcParams} + /// {markLabelId, MarkLabelCalcParams} /// - private ConcurrentDictionary MarkLabelCalcParamsDict { get; set; } = new(); + protected ConcurrentDictionary MarkLabelCalcParamsDict { get; set; } = new(); + + /// + /// {markLabelId, MarkLabelCalcParams} + /// + protected ConcurrentDictionary MarkLabelCalcResultDict { get; set; } = new(); #endregion Attr @@ -144,39 +149,38 @@ public abstract class MarkSearcherBase /// 计算标签位置过程 /// /// - public List Search() + protected void Search() { - List resultList = new(); if (World2CameraMatrix == null || MarkLabelCalcParamsDict.IsEmpty) - return resultList; + return; foreach (MarkLabelCalcParams item in MarkLabelCalcParamsDict.Values) { - MarkLabelCalcResult labelCalcResult = SearchMarkLabel(item); - resultList.Add(labelCalcResult); + MarkLabelCalcResult result = SearchMarkLabel(item); + if (!MarkLabelCalcParamsDict.ContainsKey(item.Id)) return; + MarkLabelCalcResultDict[item.Id] = result; } - return resultList; } - public async Task> SearchAsync() + protected async Task SearchAsync() { - List resultList = new(); if (World2CameraMatrix == null || MarkLabelCalcParamsDict.IsEmpty) - return resultList; + return; List tasks = new(); foreach (MarkLabelCalcParams item in MarkLabelCalcParamsDict.Values) { tasks.Add(Task.Run(() => { - resultList.Add(SearchMarkLabel(item)); + MarkLabelCalcResult result = SearchMarkLabel(item); + if (!MarkLabelCalcParamsDict.ContainsKey(item.Id)) return; + MarkLabelCalcResultDict[item.Id] = result; })); } await Task.WhenAll(tasks); - return resultList; } - private MarkLabelCalcResult SearchMarkLabel(MarkLabelCalcParams item) + protected MarkLabelCalcResult SearchMarkLabel(MarkLabelCalcParams item) { Matrix labelC2WMatrix = ConvertCameraToWorld(item); Matrix labelPointMatrix = new DenseMatrix(3, 1, new double[] @@ -255,6 +259,7 @@ public abstract class MarkSearcherBase { CameraCalcParams.PtzInfo = ptzInfo; World2CameraMatrix = ConvertWorldToCamera(CameraCalcParams); + Search(); } } @@ -265,7 +270,9 @@ public abstract class MarkSearcherBase /// public bool AddMarkLabelCalcParams(MarkLabelCalcParams labelCalcParams) { - return MarkLabelCalcParamsDict.TryAdd(labelCalcParams.Id, labelCalcParams); + long markLabelId = labelCalcParams.Id; + return MarkLabelCalcParamsDict.TryAdd(markLabelId, labelCalcParams) + && MarkLabelCalcResultDict.TryAdd(markLabelId, SearchMarkLabel(labelCalcParams)); } /// @@ -275,7 +282,8 @@ public abstract class MarkSearcherBase /// public bool DeleteMarkLabelCalcParams(long markLabelId) { - return MarkLabelCalcParamsDict.TryRemove(markLabelId, out _); + return MarkLabelCalcParamsDict.TryRemove(markLabelId, out _) + && MarkLabelCalcResultDict.TryRemove(markLabelId, out _); } /// @@ -288,5 +296,33 @@ public abstract class MarkSearcherBase return MarkLabelCalcParamsDict.ContainsKey(markLabelId); } + public List GetMarkLabelCalcResultList() + { + return MarkLabelCalcResultDict.Values.ToList(); + } + #endregion Base Method + + #region Base Method Async + + /// + /// 更新相机计算参数 + /// + /// + public async Task UpdateCameraCalcParamsAsync(PtzInfo ptzInfo) + { + if (IsCameraRotate(ptzInfo)) + { + CameraCalcParams.PtzInfo = ptzInfo; + World2CameraMatrix = ConvertWorldToCamera(CameraCalcParams); + await SearchAsync(); + } + } + + public async Task> GetMarkLabelCalcResultListAsync() + { + return await Task.Run(GetMarkLabelCalcResultList); + } + + #endregion Base Method Async } \ No newline at end of file diff --git a/Cis.Application/Core/Service/MarkSearchService.cs b/Cis.Application/Core/Service/MarkSearchService.cs index 59cdc34..cd3ba3f 100644 --- a/Cis.Application/Core/Service/MarkSearchService.cs +++ b/Cis.Application/Core/Service/MarkSearchService.cs @@ -7,14 +7,12 @@ public class MarkSearchService : IDynamicApiController, ITransient { #region Attr - private readonly CameraDataCenter _cameraDataCenter; private readonly IMarkSearcherServer _markSearcherServer; #endregion Attr public MarkSearchService(CameraDataCenter cameraDataCenter, IMarkSearcherServer markSearcherServer) { - _cameraDataCenter = cameraDataCenter; _markSearcherServer = markSearcherServer; } @@ -57,6 +55,6 @@ public class MarkSearchService : IDynamicApiController, ITransient [HttpGet] public async Task> GetMarkLabelCalcResultList(long cameraId) { - return await _cameraDataCenter.GetMarkLabelCalcResultListAsync(cameraId); + return await _markSearcherServer.GetMarkLabelCalcResultListAsync(cameraId); } } \ No newline at end of file diff --git a/Cis.Web.Entry/Program.cs b/Cis.Web.Entry/Program.cs index d4212d2..c19f1b5 100644 --- a/Cis.Web.Entry/Program.cs +++ b/Cis.Web.Entry/Program.cs @@ -1,5 +1,15 @@ +using Furion.Logging; + +// δ쳣 +AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); +// webServer Serve.Run(RunOptions.Default.AddWebComponent().WithArgs(args)); +static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) +{ + Log.Error(sender?.ToString(), e); +} + public class WebComponent : IWebComponent { public void Load(WebApplicationBuilder builder, ComponentContext componentContext)