Browse Source

修复了历史任务的BUG

zoulei 1 year ago
parent
commit
e43ab694b4

+ 1 - 1
Service/CapMoni/App.config

@@ -4,7 +4,7 @@
 		<!--采集文件存放目录-->
 		<add key="FileDir" value="C:\"/>
 		<!--采集时长(S)-->
-		<add key="Duration" value="6"/>
+		<add key="Duration" value="60"/>
 		<!--频点(MHz)多个-->
 		<add key="Freqs" value="310.85;310.95;311;312;313;314;315;316;317"/>
 	</appSettings>

+ 8 - 6
Service/CapMoni/Program.cs

@@ -86,19 +86,21 @@ namespace CapMoni
                     filePath = Path.Combine(fileDirDate, $"{fileName}.dat");
                     BinaryWriter datFile3 = new BinaryWriter(new FileStream(filePath, FileMode.Create), Encoding.UTF8);
 
-                    Thread.Sleep(durationInt * 1000);
                     var dataCon = File.ReadAllBytes("1.dat");
-                    datFile1.Write(dataCon);
-                    datFile2.Write(dataCon);
-                    datFile3.Write(dataCon);
-                    //Thread.Sleep(6000);
+                    var count = durationInt / 15;
+                    for (int i = 0; i < count; i++)
+                    {
+                        datFile1.Write(dataCon);
+                        datFile2.Write(dataCon);
+                        datFile3.Write(dataCon);
+                    }
                     datFile1.Flush();
                     datFile1.Close();
                     datFile2.Flush();
                     datFile2.Close();
                     datFile3.Flush();
                     datFile3.Close();
-
+                    Thread.Sleep(durationInt * 1000);
                     Console.WriteLine($"{filePath}采集完毕");
                 });
             }

+ 1 - 1
Service/X2D1TaskServer/App.config

@@ -27,7 +27,7 @@
 		<add key="AdjaSatDelay" value="0"/>
 
 		<!--检测文件类型(上行信号=0,主星下行信号=1)-->
-		<add key="CheckFileType" value="0"/>
+		<add key="CheckFileType" value="1"/>
 
 		<!--并行处理线程个数(支持0到N,0表示不限制,每个频点都在独立的线程中处理)-->
 		<add key="ThreadCount" value="0"/>

+ 1238 - 0
Service/X2D1TaskServer/Service/TaskService - 副本.cs

@@ -0,0 +1,1238 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using XdCxRhDW.Dto;
+
+namespace X2D1TaskServer.Service
+{
+    public class TaskService
+    {
+        private readonly string baseUrl;
+        int capSeconds;
+        double? mainSatDelay;//配置文件中配置的主星转发延迟
+        double? adjaSatDelay;//配置文件中配置的邻星转发延迟
+        int checkFileType; //检测文件类型(上行信号= 0, 主星下行信号= 1
+        int threadCount = 0;//线程个数
+        Dictionary<int, CancellationTokenSource> dicCts = new Dictionary<int, CancellationTokenSource>();
+        public TaskService()
+        {
+            try
+            {
+                var posPlatformAddr = ConfigurationManager.AppSettings["PosPlatformAddr"].Trim();//like http://127.0.0.1:8091 or http://127.0.0.1:8091/
+                if (posPlatformAddr.EndsWith("/"))
+                    this.baseUrl = posPlatformAddr + "api/";
+                else
+                    this.baseUrl = posPlatformAddr + "/api/";
+                var val = ConfigurationManager.AppSettings["CapSeconds"].Trim();
+                capSeconds = Convert.ToInt32(val);
+                if (!int.TryParse(val, out capSeconds))
+                {
+                    capSeconds = 60;
+                }
+                string mainSatDelayStr = ConfigurationManager.AppSettings["MainSatDelay"];
+                if (!string.IsNullOrWhiteSpace(mainSatDelayStr))
+                {
+                    mainSatDelay = Convert.ToDouble(mainSatDelayStr);
+                }
+                string adjaSatDelayStr = ConfigurationManager.AppSettings["AdjaSatDelay"];
+                if (!string.IsNullOrWhiteSpace(adjaSatDelayStr))
+                {
+                    adjaSatDelay = Convert.ToDouble(adjaSatDelayStr);
+                }
+                checkFileType = Convert.ToInt32(ConfigurationManager.AppSettings["CheckFileType"]);
+                int.TryParse(ConfigurationManager.AppSettings["ThreadCount"], out threadCount);
+                if (threadCount < 0) threadCount = 0;
+
+            }
+            catch (Exception ex)
+            {
+                LogHelper.Error("读取配置文件异常", ex).Wait(5000);
+            }
+        }
+
+        /// <summary>
+        /// 启动历史任务
+        /// </summary>
+        /// <param name="dto"></param>
+        public void StartHistoryAsync(X2D1TaskHandleDto dto)
+        {
+            var cts = new CancellationTokenSource();
+            if (dicCts.ContainsKey(dto.ID))
+                dicCts[dto.ID] = cts;
+            else
+                dicCts.Add(dto.ID, cts);
+
+            Task.Run(async () =>
+            {
+                if (!Directory.Exists(dto.CapDir))
+                {
+                    await StopTask(dto.ID, EnumTaskStopType.Error, $"文件路径[{dto.CapDir}]不存在,任务结束");
+                    return;
+                }
+                if (dto.DateDirFormat.Contains("\\"))
+                {
+                    await StopTask(dto.ID, EnumTaskStopType.Error, $"子目录日期格式不能包含多级目录格式");
+                    return;
+                }
+
+
+
+                await LogHelper.Info($"【任务{dto.ID}】开始执行...");
+                int.TryParse(ConfigurationManager.AppSettings["PosDtoFactor"], out int posDtoFactor);
+                if (posDtoFactor == 0) posDtoFactor = 1;//定位时时差系数
+                await LogHelper.Info($"【任务{dto.ID}】定位时差系数={posDtoFactor}");
+                string checkFileTypeStr = "上行信号";
+                if (checkFileType != 0)
+                    checkFileTypeStr = "主星下行信号";
+                await LogHelper.Info($"【任务{dto.ID}】检测类型={checkFileTypeStr}");
+                string threadStr = threadCount == 0 ? "不限制" : threadCount.ToString();
+                await LogHelper.Info($"【任务{dto.ID}】线程个数={threadStr}");
+                bool canConnected = CanGetSatIdFromMySql(dto.ID);
+                foreach (var taskSig in dto.Sigs)
+                {
+                    double? delay1 = taskSig.SigDelay.FirstOrDefault(p => p.SatInfoSatCode == dto.MainSatCode)?.Delay;
+                    double? delay2 = taskSig.SigDelay.FirstOrDefault(p => p.SatInfoSatCode == dto.AdjaSatCode)?.Delay;
+                    if (delay1 == null)
+                        delay1 = mainSatDelay;
+                    if (delay2 == null)
+                        delay2 = adjaSatDelay;
+                    if (delay1 == null) delay1 = 0;
+                    if (delay2 == null) delay2 = 0;
+
+                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],主星{dto.MainSatCode}转发时延{delay1}us");
+                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],邻星{dto.AdjaSatCode}转发时延{delay2}us");
+                }
+
+                DateTime preTime = dto.StartTime.AddSeconds(-1);
+                int formatFlag;
+                if (string.IsNullOrWhiteSpace(dto.DateDirFormat))
+                {
+                    //没有日期目录,处理完目录中的数据后停止任务
+                    formatFlag = 0;
+                }
+                else if (dto.DateDirFormat.ToLower().EndsWith("dd"))
+                {
+                    //处理完一个目录后跳转到第二天的目录
+                    formatFlag = 1;
+                }
+                else if (dto.DateDirFormat.ToUpper().EndsWith("HH"))
+                {
+                    //处理完一个目录后跳转到下一个小时的目录
+                    formatFlag = 2;
+                }
+                else
+                {
+                    await StopTask(dto.ID, EnumTaskStopType.Error, $"执行异常,不支持的日期目录格式");
+                    return;
+                }
+
+                while (!cts.IsCancellationRequested && preTime <= dto.EndTime)
+                {
+                    if (!dicCts.Values.Contains(cts)) return;
+                    string filesDir = dto.CapDir;
+                    try
+                    {
+                        if (formatFlag != 0)
+                        {
+                            filesDir = Path.Combine(dto.CapDir, $"{preTime.ToString(dto.DateDirFormat)}");//yyyyMMdd
+                        }
+
+                        if (!Directory.Exists(filesDir))
+                        {
+                            await LogHelper.Info($"【任务{dto.ID}】目录[{filesDir}]不存在,跳过此目录");
+                            ResetTime(formatFlag, ref preTime);
+                            continue;
+                        }
+
+
+                        await LogHelper.Info($"【任务{dto.ID}】正在扫描[{filesDir}]目录...");
+                        Stopwatch sw = new Stopwatch();
+                        sw.Start();
+                        List<string> files = Directory.GetFiles(filesDir, "*.dat").ToList();
+                        sw.Stop();
+                        await LogHelper.Info($"【任务{dto.ID}】扫描[{filesDir}]目录完成,耗时{sw.ElapsedMilliseconds}ms");
+                        if (!files.Any())
+                        {
+                            await LogHelper.Info($"【任务{dto.ID}】目录[{filesDir}]中没有文件,跳过此目录");
+                            ResetTime(formatFlag, ref preTime);
+                            continue;
+                        }
+                        bool isLocal = IsLocal(filesDir);
+                        List<IGrouping<DateTime, HistoryFile>> groups = null;
+                        groups = files.Select(f => FileToHistoryFile(dto, f, preTime, canConnected, cts.Token)).GroupBy(m => m.CapTime).OrderBy(m => m.Key).ToList();
+                        if (cts.IsCancellationRequested) break;
+                        foreach (var sameTimeFiles in groups)
+                        {
+                            if (cts.IsCancellationRequested) break;
+                            var xdgbInfos = sameTimeFiles.GroupBy(m => m.XdIndex);
+
+                            var splitXdgbInfos = SplitFreqFiles(xdgbInfos);
+                            List<Task> listTask = new List<Task>();
+                            foreach (var item in splitXdgbInfos)//splitXdgbInfos中的数据并行处理
+                            {
+                                if (cts.IsCancellationRequested) return;
+                                var task = Task.Run(async () =>
+                                {
+                                    foreach (var xdInfos in item)//item中的数据串行处理
+                                    {
+                                        var finfos = xdInfos.ToList();
+                                        var capTime = finfos.First().CapTime;
+                                        if (capTime < dto.StartTime) continue;
+                                        if (capTime > dto.EndTime) continue;
+                                        if (finfos.Count < 3)
+                                        {
+                                            await LogHelper.Warning($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻文件数量只有{finfos.Count}个,跳过此组数据");
+                                            continue;
+                                        }
+                                        //超短波信号
+                                        var dinfo = finfos.FirstOrDefault(m => m.Ch == 1);
+                                        if (dinfo == null)
+                                        {
+                                            await LogHelper.Warning($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻未找到超短波信号ch1文件,跳过此组数据");
+                                            continue;
+                                        }
+                                        var taskSig = dto.Sigs.FirstOrDefault(p => p.FreqUp == dinfo.FreqHz);
+                                        if (taskSig == null)
+                                        {
+                                            continue;//跳过不是任务处理的频点
+                                        }
+                                        //主星
+                                        var minfo = finfos.FirstOrDefault(m => m.Ch == 2);
+                                        if (minfo == null)
+                                        {
+                                            await LogHelper.Warning($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6}],{capTime:yyyyMMddHHmmss}时刻未找到主星信号ch2文件,跳过此组数据");
+                                            continue;
+                                        }
+                                        //邻1
+                                        var ninfo = finfos.FirstOrDefault(m => m.Ch == 3);
+                                        if (ninfo == null)
+                                        {
+                                            await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6}],{capTime:yyyyMMddHHmmss}时刻未找到邻星信号ch3文件,跳过此组数据");
+                                            continue;
+                                        }
+                                        try
+                                        {
+                                            double? delay1 = taskSig.SigDelay.FirstOrDefault(p => p.SatInfoSatCode == minfo.SatId)?.Delay;
+                                            double? delay2 = taskSig.SigDelay.FirstOrDefault(p => p.SatInfoSatCode == ninfo.SatId)?.Delay;
+                                            if (delay1 == null)
+                                                delay1 = mainSatDelay;
+                                            if (delay2 == null)
+                                                delay2 = adjaSatDelay;
+                                            if (delay1 == null) delay1 = 0;
+                                            if (delay2 == null) delay2 = 0;
+
+                                            string localFile1 = minfo.FilePath;
+                                            string localFile2 = ninfo.FilePath;
+                                            string localFile3 = dinfo.FilePath;
+                                            if (!isLocal)
+                                            {
+                                                long size = 0;
+                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻三路采集文件正在拉取到本地...");
+                                                Stopwatch sw2 = new Stopwatch();
+                                                sw2.Start();
+                                                localFile1 = $"wwwroot\\{Path.GetFileName(minfo.FilePath)}";
+                                                using (FileStream fs = new FileStream(localFile1, FileMode.Create))
+                                                {
+                                                    using (FileStream fs2 = new FileStream(minfo.FilePath, FileMode.Open))
+                                                    {
+                                                        size += fs2.Length;
+                                                        while (fs2.Position < fs2.Length)
+                                                        {
+                                                            if (cts.IsCancellationRequested) return;
+                                                            byte[] data = new byte[1024];
+                                                            var len = fs2.Read(data, 0, 1024);
+                                                            data = data.Take(len).ToArray();
+                                                            fs.Write(data, 0, len);
+                                                        }
+                                                    }
+                                                }
+                                                localFile2 = $"wwwroot\\{Path.GetFileName(ninfo.FilePath)}";
+                                                using (FileStream fs = new FileStream(localFile2, FileMode.Create))
+                                                {
+                                                    using (FileStream fs2 = new FileStream(ninfo.FilePath, FileMode.Open))
+                                                    {
+                                                        size += fs2.Length;
+                                                        while (fs2.Position < fs2.Length)
+                                                        {
+                                                            if (cts.IsCancellationRequested) return;
+                                                            byte[] data = new byte[1024];
+                                                            var len = fs2.Read(data, 0, 1024);
+                                                            data = data.Take(len).ToArray();
+                                                            fs.Write(data, 0, len);
+                                                        }
+                                                    }
+                                                }
+                                                localFile3 = $"wwwroot\\{Path.GetFileName(dinfo.FilePath)}";
+                                                using (FileStream fs = new FileStream(localFile3, FileMode.Create))
+                                                {
+                                                    using (FileStream fs2 = new FileStream(dinfo.FilePath, FileMode.Open))
+                                                    {
+                                                        size += fs2.Length;
+                                                        while (fs2.Position < fs2.Length)
+                                                        {
+                                                            if (cts.IsCancellationRequested) return;
+                                                            byte[] data = new byte[1024];
+                                                            var len = fs2.Read(data, 0, 1024);
+                                                            data = data.Take(len).ToArray();
+                                                            fs.Write(data, 0, len);
+                                                        }
+                                                    }
+
+                                                }
+
+                                                sw2.Stop();
+                                                var spped = size / 1024d / 1024d / (sw2.ElapsedMilliseconds / 1000d);
+                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻三路采集文件拉取到本地完成,共耗时{sw2.ElapsedMilliseconds}ms,平均速率{spped:f2}MB/s");
+                                            }
+
+                                            string mainFile = await HttpHelper.UploadFileAsync(localFile1, baseUrl, token: cts.Token);//主星文件
+                                            string adjaFile = await HttpHelper.UploadFileAsync(localFile2, baseUrl, token: cts.Token);//邻星文件
+                                            string cdbFile = await HttpHelper.UploadFileAsync(localFile3, baseUrl, token: cts.Token);//超短文件
+                                            if (!isLocal)
+                                            {
+                                                File.Delete(localFile1);
+                                                File.Delete(localFile2);
+                                                File.Delete(localFile3);
+                                            }
+
+                                            DetectDto detectDto = new DetectDto()
+                                            {
+                                                file1 = cdbFile,//使用上行泄露信号进行检测
+                                                dmcType = taskSig.SigType,//上行信号检测目前的算法只能使用基于能量的KY或IBS检测
+                                                fsHz = minfo.FsHz,
+                                                mergeRes = true,
+                                                SigProc = true,
+                                                band = taskSig.BandHz / 1e3,
+                                            };
+                                            if (checkFileType == 0)//检测上行信号=0,检测主星下行信号=1
+                                            {
+                                                detectDto.dmcType = detectDto.dmcType & ~EnumSigCheckTypeDto.DAMA;//DAMA不支持上行信号检测,在这里移除掉
+                                                if ((int)detectDto.dmcType == 0)
+                                                {
+                                                    await LogHelper.Warning($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],上行信号不支持仅DAMA检测");
+                                                    continue;
+                                                }
+                                            }
+                                            else
+                                            {
+                                                detectDto.file1 = mainFile;//使用主星下行信号进行检测
+                                            }
+                                            if (detectDto.dmcType == EnumSigCheckTypeDto.Normal)
+                                            {
+                                                await LogHelper.Warning($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],该服务不支持Normal类型信号");
+                                                continue;
+                                            }
+                                            var deteResp = await HttpHelper.PostRequestAsync<List<DetectResDto>>(baseUrl + "DetectCg/DetectCalc", detectDto, token: cts.Token);
+                                            if (deteResp.code != 200)
+                                            {
+                                                await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻信号检测出错.{deteResp.msg}");
+                                                continue;
+                                            }
+                                            await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻{checkFileTypeStr}检测完成,共{deteResp.data.Count}个时隙");
+                                            var smps = deteResp.data.Select(m => new SmpPosition(m.Start, m.Length)).ToList();//怎么补0?
+                                            var cgDto = new CpuCgMultiDto()
+                                            {
+                                                dtCenter = 260000,
+                                                dtRange = 50000,
+                                                file1 = cdbFile,
+                                                file2 = mainFile,
+                                                samplingRate = minfo.FsHz,
+                                                smpPositions = smps,
+                                                snrThreshold = taskSig.Snr,
+                                                BandHz = 0,
+
+                                            };
+                                            if (checkFileType != 0)
+                                            {
+                                                cgDto.file1 = mainFile;
+                                                cgDto.file2 = cdbFile;
+                                            }
+                                            var result1 = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(baseUrl + "DetectCg/CpuCgMultiCalc", cgDto, token: cts.Token);
+                                            if (result1.code != 200)
+                                            {
+                                                await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星超短CPU参估出错.{result1.msg}");
+                                                continue;
+                                            }
+                                            await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星超短CPU参估完成.");
+                                            cgDto = new CpuCgMultiDto()
+                                            {
+                                                dtCenter = 260000,
+                                                dtRange = 50000,
+                                                file1 = cdbFile,
+                                                file2 = adjaFile,
+                                                samplingRate = minfo.FsHz,
+                                                smpPositions = smps,
+                                                snrThreshold = taskSig.Snr,
+                                                BandHz = 0,
+                                            };
+                                            if (checkFileType != 0)
+                                            {
+                                                cgDto.file1 = mainFile;
+                                                cgDto.file2 = adjaFile;
+                                                cgDto.dtCenter = 0;
+                                                cgDto.dtRange = 50000;
+                                            }
+                                            var result2 = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(baseUrl + "DetectCg/CpuCgMultiCalc", cgDto, token: cts.Token);
+                                            if (result2.code != 200)
+                                            {
+                                                if (checkFileType == 0)
+                                                    await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻邻星超短CPU参估出错.{result2.msg}");
+                                                else
+                                                    await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星邻星CPU参估出错.{result2.msg}");
+                                                continue;
+                                            }
+                                            if (checkFileType == 0)
+                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻邻星超短CPU参估完成");
+                                            else
+                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星邻星CPU参估完成");
+                                            await HttpHelper.DeleteFileAsync(baseUrl, mainFile, adjaFile, cdbFile);
+                                            var data1 = result1.data;
+                                            var data2 = result2.data;
+                                            if (data1.Count != data2.Count || data1.Count != deteResp.data.Count)
+                                            {
+                                                await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻参估结果个数和检测结果个数不匹配");
+                                                continue;
+                                            }
+                                            for (int i = 0; i < data1.Count; i++)
+                                            {
+                                                try
+                                                {
+                                                    if (cts.IsCancellationRequested) break;
+                                                    X2D1NoXlNoParlPosDto x2D1 = new X2D1NoXlNoParlPosDto()
+                                                    {
+                                                        TaskID = dto.ID,
+                                                        SigTime = minfo.CapTime.AddSeconds(data1[i].Smpstart / minfo.FsHz),
+                                                        MainCode = minfo.SatId,
+                                                        AdjaCode = ninfo.SatId,
+                                                        XdDfo = data2[i].Df,
+                                                        XdSnr = data2[i].Snr,
+                                                        SatTxLon = dto.CapLon,
+                                                        SatTxLat = dto.CapLat,
+                                                        CdbTxLon = dto.CapLon,
+                                                        CdbTxLat = dto.CapLat,
+                                                        FreqDown = minfo.FreqHz,
+                                                        FreqUp = dinfo.FreqHz,
+                                                        CheckRes = new CheckResDto()
+                                                        {
+                                                            FileName = Path.GetFileName(dinfo.FilePath),
+                                                            ModRate = deteResp.data[i].ModRate,
+                                                            ModType = deteResp.data[i].ModType,
+                                                            SmpCount = deteResp.data[i].Length,
+                                                            SmpStart = deteResp.data[i].Start,
+                                                            UserName = deteResp.data[i].UserName,
+                                                            FfcHz = deteResp.data[i].FfcHz,
+                                                            PosCheckType = deteResp.data[i].DmcType.GetEnumByDisplayName<EnumPosCheckTypeDto>(),
+                                                        }
+                                                    };
+                                                    if (data1[i].Snr > 0 && data2[i].Snr > 0)
+                                                    {
+                                                        //卫星转发某些频点可能有时延,无参定位由于不能抵消需要减去这个时延
+                                                        if (checkFileType == 0)
+                                                        {
+                                                            x2D1.SxDto = data1[i].Dt * posDtoFactor - data2[i].Dt * posDtoFactor - delay1.Value + delay2.Value;
+                                                            x2D1.SxDfo = data1[i].Df - data2[i].Df;
+                                                            x2D1.SxSnr = (data1[i].Snr + data2[i].Snr) / 2;
+                                                            x2D1.XdDto = data1[i].Dt * posDtoFactor - delay1.Value;
+                                                            x2D1.XdDfo = data1[i].Df;
+                                                            x2D1.XdSnr = data1[i].Snr;
+                                                        }
+                                                        else
+                                                        {
+                                                            x2D1.SxDto = data2[i].Dt * posDtoFactor - delay1.Value + delay2.Value;
+                                                            x2D1.SxDfo = data2[i].Df;
+                                                            x2D1.SxSnr = data2[i].Snr;
+                                                            x2D1.XdDto = data1[i].Dt * posDtoFactor - delay1.Value;
+                                                            x2D1.XdDfo = data1[i].Df;
+                                                            x2D1.XdSnr = data1[i].Snr;
+                                                        }
+                                                    }
+
+                                                    var result = await HttpHelper.PostRequestAsync<PosResDto>(baseUrl + "Pos/PosX2D1NoXlNoParAsync", x2D1);
+                                                    if (result.code != 200)
+                                                    {
+                                                        await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻时隙位置{data1[i].Smpstart}定位异常.{result.msg}");
+                                                    }
+                                                }
+                                                catch (Exception ex)
+                                                {
+                                                    await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻时隙位置{data1[i].Smpstart}定位异常", ex);
+                                                }
+                                            }
+                                            await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻定位完成");
+                                        }
+                                        catch (TaskCanceledException)
+                                        {
+                                        }
+                                        catch (Exception ex)
+                                        {
+                                            if (ex.InnerException != null && ex.InnerException.GetType() == typeof(TaskCanceledException))
+                                                await LogHelper.Warning($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻文件处理结束,用户手动终止", ex.InnerException);
+                                            else
+                                                await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻文件处理异常", ex);
+                                            continue;
+                                        }
+                                    }
+
+                                });
+                                listTask.Add(task);
+                            }
+                            await Task.WhenAll(listTask);
+                            preTime = sameTimeFiles.First().CapTime;
+                        }
+                        ResetTime(formatFlag, ref preTime);
+                        await LogHelper.Info($"【任务{dto.ID}】目录[{filesDir}]本次扫描的数据处理完成");
+                    }
+                    catch (TaskCanceledException ex)
+                    {
+                        await LogHelper.Warning($"【任务{dto.ID}】目录[{filesDir}]中的数据处理结束,用户手动终止", ex);
+                        ResetTime(formatFlag, ref preTime);
+                    }
+                    catch (Exception ex)
+                    {
+                        await LogHelper.Error($"【任务{dto.ID}】目录[{filesDir}]中的数据处理出错,跳过此目录", ex);
+                        ResetTime(formatFlag, ref preTime);
+                    }
+                }
+                await StopTask(dto.ID, EnumTaskStopType.Properly, "数据处理完成,任务结束");
+            }, cts.Token);
+        }
+
+        /// <summary>
+        /// 启动实时任务
+        /// </summary>
+        /// <param name="dto"></param>
+        public void StarRealAsync(X2D1TaskHandleDto dto)
+        {
+            var cts = new CancellationTokenSource();
+            if (dicCts.ContainsKey(dto.ID))
+                dicCts[dto.ID] = cts;
+            else
+                dicCts.Add(dto.ID, cts);
+
+            Task.Run(async () =>
+            {
+                if (!Directory.Exists(dto.CapDir))
+                {
+                    await StopTask(dto.ID, EnumTaskStopType.Error, $"文件路径[{dto.CapDir}]不存在,任务结束");
+                    return;
+                }
+                if (dto.DateDirFormat.Contains("\\"))
+                {
+                    await StopTask(dto.ID, EnumTaskStopType.Error, $"子目录日期格式不能包含多级目录格式");
+                    return;
+                }
+
+                await LogHelper.Info($"【任务{dto.ID}】开始执行...");
+                int.TryParse(ConfigurationManager.AppSettings["PosDtoFactor"], out int posDtoFactor);
+                if (posDtoFactor == 0) posDtoFactor = 1;//定位时时差系数
+                await LogHelper.Info($"【任务{dto.ID}】定位时差系数={posDtoFactor}");
+                string checkFileTypeStr = "上行信号";
+                if (checkFileType != 0)
+                    checkFileTypeStr = "主星下行信号";
+                await LogHelper.Info($"【任务{dto.ID}】检测类型={checkFileTypeStr}");
+                string threadStr = threadCount == 0 ? "不限制" : threadCount.ToString();
+                await LogHelper.Info($"【任务{dto.ID}】线程个数={threadStr}");
+                bool canConnected = CanGetSatIdFromMySql(dto.ID);
+                foreach (var taskSig in dto.Sigs)
+                {
+                    double? delay1 = taskSig.SigDelay.FirstOrDefault(p => p.SatInfoSatCode == dto.MainSatCode)?.Delay;
+                    double? delay2 = taskSig.SigDelay.FirstOrDefault(p => p.SatInfoSatCode == dto.AdjaSatCode)?.Delay;
+                    if (delay1 == null)
+                        delay1 = mainSatDelay;
+                    if (delay2 == null)
+                        delay2 = adjaSatDelay;
+                    if (delay1 == null) delay1 = 0;
+                    if (delay2 == null) delay2 = 0;
+
+                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],主星{dto.MainSatCode}转发时延{delay1}us");
+                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],邻星{dto.AdjaSatCode}转发时延{delay2}us");
+                }
+
+                DateTime preTime = DateTime.Now.AddSeconds(-capSeconds * 2);
+                int formatFlag;
+                if (string.IsNullOrWhiteSpace(dto.DateDirFormat))
+                {
+                    //没有日期目录,处理完目录中的数据后停止任务
+                    formatFlag = 0;
+                }
+                else if (dto.DateDirFormat.ToLower().EndsWith("dd"))
+                {
+                    //处理完一个目录后跳转到第二天的目录
+                    formatFlag = 1;
+                }
+                else if (dto.DateDirFormat.ToUpper().EndsWith("HH"))
+                {
+                    //处理完一个目录后跳转到下一个小时的目录
+                    formatFlag = 2;
+                }
+                else
+                {
+                    await StopTask(dto.ID, EnumTaskStopType.Error, $"执行异常,不支持的日期目录格式");
+                    return;
+                }
+
+                while (!cts.IsCancellationRequested)
+                {
+                    string filesDir = dto.CapDir;
+                    try
+                    {
+                        if (formatFlag != 0)
+                        {
+                            filesDir = Path.Combine(dto.CapDir, $"{preTime.ToString(dto.DateDirFormat)}");//yyyy_MM_dd_HH
+                        }
+                        bool doNextHour = false;
+                        while (!Directory.Exists(filesDir))
+                        {
+                            if (cts.IsCancellationRequested) return;
+                            if (!dicCts.Values.Contains(cts)) return;
+                            await LogHelper.Info($"【任务{dto.ID}】目录[{filesDir}]不存在,等待5秒...");
+                            await Task.Delay(5000, cts.Token);
+                            if (DateTime.Now.Hour != preTime.Hour)
+                            {
+                                ResetTime(formatFlag, ref preTime);
+                                doNextHour = true;
+                                break;
+                            }
+                        }
+                        if (cts.IsCancellationRequested) return;
+                        if (doNextHour)
+                        {
+                            continue;
+                        }
+                        await LogHelper.Info($"【任务{dto.ID}】正在扫描[{filesDir}]目录...");
+                        Stopwatch sw = new Stopwatch();
+                        sw.Start();
+                        List<string> files = Directory.GetFiles(filesDir, "*.dat").ToList();
+                        sw.Stop();
+                        await LogHelper.Info($"【任务{dto.ID}】扫描[{filesDir}]目录完成,耗时{sw.ElapsedMilliseconds}ms");
+                        while (true)
+                        {
+                            if (cts.IsCancellationRequested) return;
+                            if (!files.Any())
+                            {
+                                await LogHelper.Info($"【任务{dto.ID}】目录[{filesDir}]中没有文件,等待10秒...");
+                                if (DateTime.Now.Hour != preTime.Hour)
+                                {
+                                    ResetTime(formatFlag, ref preTime);
+                                    doNextHour = true;
+                                    break;
+                                }
+                                await Task.Delay(10000, cts.Token);
+                                files = Directory.GetFiles(filesDir, "*.dat").ToList();
+                                continue;
+                            }
+                            break;
+                        }
+                        if (cts.IsCancellationRequested) return;
+                        List<IGrouping<DateTime, HistoryFile>> groups = null;
+                        bool isLocal = IsLocal(filesDir);
+                        groups = files.Select(f => FileToHistoryFile(dto, f, preTime, canConnected, cts.Token)).Where(p => p != null).GroupBy(m => m.CapTime).OrderBy(m => m.Key).ToList();
+                        if (cts.IsCancellationRequested) break;
+                        bool hasFile = false;
+                        if (groups.Any())
+                        {
+                            var lastTime = groups.Last().Key;
+                            foreach (var sameTimeFiles in groups)
+                            {
+                                if (cts.IsCancellationRequested) return;
+                                var capTime = sameTimeFiles.First().CapTime;
+                                if ((DateTime.Now - capTime).TotalMinutes > 10)
+                                {
+                                    preTime = capTime;
+                                    await LogHelper.Warning($"【任务{dto.ID}】处理速度过慢,丢弃数据");
+                                    continue;
+                                }
+                                if (capTime == lastTime)
+                                {
+                                    await WaitFileEnd(dto.ID, sameTimeFiles.First(), capSeconds, cts);
+                                }
+                                await LogHelper.Info($"【任务{dto.ID}】[{capTime:yyyyMMddHHmmss}]时刻文件采集完成");
+                                if (!CanOpenFile(dto.ID, sameTimeFiles.First()))
+                                    continue;//文件无法打开
+                                hasFile = true;
+                                var xdgbInfos = sameTimeFiles.GroupBy(m => m.XdIndex);
+                                var splitXdgbInfos = SplitFreqFiles(xdgbInfos);
+                                List<Task> listTask = new List<Task>();
+                                foreach (var item in splitXdgbInfos)//splitXdgbInfos中的数据并行处理
+                                {
+                                    if (cts.IsCancellationRequested) return;
+                                    var task = Task.Run(async () =>
+                                    {
+                                        foreach (var xdInfos in item)//item中的数据串行处理
+                                        {
+
+                                            var finfos = xdInfos.ToList();
+                                            if (finfos.Count < 3)
+                                            {
+                                                await LogHelper.Warning($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻文件数量只有{finfos.Count}个,跳过此组数据");
+                                                continue;
+                                            }
+                                            //超短波信号
+                                            var dinfo = finfos.FirstOrDefault(m => m.Ch == 1);
+                                            if (dinfo == null)
+                                            {
+                                                await LogHelper.Warning($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻未找到超短波信号ch1文件,跳过此组数据");
+                                                continue;
+                                            }
+                                            var taskSig = dto.Sigs.FirstOrDefault(p => p.FreqUp == dinfo.FreqHz);
+                                            if (taskSig == null)
+                                            {
+                                                continue;//跳过不是任务处理的频点
+                                            }
+                                            //主星
+                                            var minfo = finfos.FirstOrDefault(m => m.Ch == 2);
+                                            if (minfo == null)
+                                            {
+                                                await LogHelper.Warning($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6}],{capTime:yyyyMMddHHmmss}时刻未找到主星信号ch2文件,跳过此组数据");
+                                                continue;
+                                            }
+                                            //邻1
+                                            var ninfo = finfos.FirstOrDefault(m => m.Ch == 3);
+                                            if (ninfo == null)
+                                            {
+                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6}],{capTime:yyyyMMddHHmmss}时刻未找到邻星信号ch3文件,跳过此组数据");
+                                                continue;
+                                            }
+                                            try
+                                            {
+                                                double? delay1 = taskSig.SigDelay.FirstOrDefault(p => p.SatInfoSatCode == minfo.SatId)?.Delay;
+                                                double? delay2 = taskSig.SigDelay.FirstOrDefault(p => p.SatInfoSatCode == ninfo.SatId)?.Delay;
+                                                if (delay1 == null)
+                                                    delay1 = mainSatDelay;
+                                                if (delay2 == null)
+                                                    delay2 = adjaSatDelay;
+                                                if (delay1 == null) delay1 = 0;
+                                                if (delay2 == null) delay2 = 0;
+                                                string localFile1 = minfo.FilePath;
+                                                string localFile2 = ninfo.FilePath;
+                                                string localFile3 = dinfo.FilePath;
+                                                if (!isLocal)
+                                                {
+                                                    long size = 0;
+                                                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻三路采集文件正在拉取到本地...");
+                                                    Stopwatch sw2 = new Stopwatch();
+                                                    sw2.Start();
+                                                    localFile1 = $"wwwroot\\{Path.GetFileName(minfo.FilePath)}";
+                                                    using (FileStream fs = new FileStream(localFile1, FileMode.Create))
+                                                    {
+                                                        using (FileStream fs2 = new FileStream(minfo.FilePath, FileMode.Open))
+                                                        {
+                                                            size += fs2.Length;
+                                                            while (fs2.Position < fs2.Length)
+                                                            {
+                                                                if (cts.IsCancellationRequested) return;
+                                                                byte[] data = new byte[1024];
+                                                                var len = fs2.Read(data, 0, 1024);
+                                                                data = data.Take(len).ToArray();
+                                                                fs.Write(data, 0, len);
+                                                            }
+                                                        }
+                                                    }
+                                                    localFile2 = $"wwwroot\\{Path.GetFileName(ninfo.FilePath)}";
+                                                    using (FileStream fs = new FileStream(localFile2, FileMode.Create))
+                                                    {
+                                                        using (FileStream fs2 = new FileStream(ninfo.FilePath, FileMode.Open))
+                                                        {
+                                                            size += fs2.Length;
+                                                            while (fs2.Position < fs2.Length)
+                                                            {
+                                                                if (cts.IsCancellationRequested) return;
+                                                                byte[] data = new byte[1024];
+                                                                var len = fs2.Read(data, 0, 1024);
+                                                                data = data.Take(len).ToArray();
+                                                                fs.Write(data, 0, len);
+                                                            }
+                                                        }
+                                                    }
+                                                    localFile3 = $"wwwroot\\{Path.GetFileName(dinfo.FilePath)}";
+                                                    using (FileStream fs = new FileStream(localFile3, FileMode.Create))
+                                                    {
+                                                        using (FileStream fs2 = new FileStream(dinfo.FilePath, FileMode.Open))
+                                                        {
+                                                            size += fs2.Length;
+                                                            while (fs2.Position < fs2.Length)
+                                                            {
+                                                                if (cts.IsCancellationRequested) return;
+                                                                byte[] data = new byte[1024];
+                                                                var len = fs2.Read(data, 0, 1024);
+                                                                data = data.Take(len).ToArray();
+                                                                fs.Write(data, 0, len);
+                                                            }
+                                                        }
+                                                    }
+                                                    sw2.Stop();
+                                                    var spped = size / 1024d / 1024d / (sw2.ElapsedMilliseconds / 1000d);
+                                                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻三路采集文件拉取到本地完成,共耗时{sw2.ElapsedMilliseconds}ms,平均速率{spped:f2}MB/s");
+                                                }
+                                                string mainFile = await HttpHelper.UploadFileAsync(localFile1, baseUrl, token: cts.Token);//主星文件
+                                                string adjaFile = await HttpHelper.UploadFileAsync(localFile2, baseUrl, token: cts.Token);//邻星文件
+                                                string cdbFile = await HttpHelper.UploadFileAsync(localFile3, baseUrl, token: cts.Token);//超短文件
+                                                if (!isLocal)
+                                                {
+                                                    File.Delete(localFile1);
+                                                    File.Delete(localFile2);
+                                                    File.Delete(localFile3);
+                                                }
+                                                DetectDto detectDto = new DetectDto()
+                                                {
+                                                    file1 = cdbFile,//11局使用上行泄露信号进行检测
+                                                    dmcType = taskSig.SigType,//上行信号检测目前的算法只能使用基于能量的KY或IBS检测
+                                                    fsHz = minfo.FsHz,
+                                                    band = taskSig.BandHz / 1e3,
+                                                    mergeRes = true,
+                                                    SigProc = true,
+                                                };
+                                                if (checkFileType == 0)//检测上行信号=0,检测主星下行信号=1
+                                                {
+                                                    detectDto.dmcType = detectDto.dmcType & ~EnumSigCheckTypeDto.DAMA;//DAMA不支持上行信号检测,在这里移除掉
+                                                    if ((int)detectDto.dmcType == 0)
+                                                    {
+                                                        await LogHelper.Warning($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],上行信号不支持仅DAMA检测");
+                                                        continue;
+                                                    }
+                                                }
+                                                else
+                                                {
+                                                    detectDto.file1 = mainFile;//使用主星下行信号进行检测
+                                                }
+                                                if (detectDto.dmcType == EnumSigCheckTypeDto.Normal)
+                                                {
+                                                    await LogHelper.Warning($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],该服务不支持Normal类型信号");
+                                                    continue;
+                                                }
+                                                var deteResp = await HttpHelper.PostRequestAsync<List<DetectResDto>>(baseUrl + "DetectCg/DetectCalc", detectDto, token: cts.Token);
+                                                if (deteResp.code != 200)
+                                                {
+                                                    await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻信号检测出错.{deteResp.msg}");
+                                                    continue;
+                                                }
+                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻信号检测完成,共{deteResp.data.Count}个时隙");
+                                                var smps = deteResp.data.Select(m => new SmpPosition(m.Start, m.Length)).ToList();//怎么补0?
+                                                var cgDto = new CpuCgMultiDto()
+                                                {
+                                                    dtCenter = 260000,
+                                                    dtRange = 50000,
+                                                    file1 = cdbFile,
+                                                    file2 = mainFile,
+                                                    samplingRate = minfo.FsHz,
+                                                    smpPositions = smps,
+                                                    snrThreshold = taskSig.Snr,
+                                                    BandHz = 0,
+                                                };
+                                                if (checkFileType != 0)
+                                                {
+                                                    cgDto.file1 = mainFile;
+                                                    cgDto.file2 = cdbFile;
+                                                }
+                                                var result1 = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(baseUrl + "DetectCg/CpuCgMultiCalc", cgDto, token: cts.Token);
+                                                if (result1.code != 200)
+                                                {
+                                                    await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星超短CPU参估出错.{result1.msg}");
+                                                    continue;
+                                                }
+                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星超短CPU参估完成.");
+                                                cgDto = new CpuCgMultiDto()
+                                                {
+                                                    dtCenter = 260000,
+                                                    dtRange = 50000,
+                                                    file1 = cdbFile,
+                                                    file2 = adjaFile,
+                                                    samplingRate = minfo.FsHz,
+                                                    smpPositions = smps,
+                                                    snrThreshold = taskSig.Snr,
+                                                    BandHz = 0,
+                                                };
+                                                if (checkFileType != 0)
+                                                {
+                                                    cgDto.file1 = mainFile;
+                                                    cgDto.file2 = adjaFile;
+                                                    cgDto.dtCenter = 0;
+                                                    cgDto.dtRange = 50000;
+                                                }
+                                                var result2 = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(baseUrl + "DetectCg/CpuCgMultiCalc", cgDto, token: cts.Token);
+                                                if (result2.code != 200)
+                                                {
+                                                    if (checkFileType == 0)
+                                                        await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻邻星超短CPU参估出错.{result2.msg}");
+                                                    else
+                                                        await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星邻星CPU参估出错.{result2.msg}");
+                                                    continue;
+                                                }
+                                                if (checkFileType == 0)
+                                                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻邻星超短CPU参估完成");
+                                                else
+                                                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星邻星CPU参估完成");
+                                                await HttpHelper.DeleteFileAsync(baseUrl, mainFile, adjaFile, cdbFile);
+                                                var data1 = result1.data;
+                                                var data2 = result2.data;
+                                                if (data1.Count != data2.Count || data1.Count != deteResp.data.Count)
+                                                {
+                                                    await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻参估结果个数和检测结果个数不匹配");
+                                                    continue;
+                                                }
+                                                for (int i = 0; i < data1.Count; i++)
+                                                {
+                                                    try
+                                                    {
+                                                        if (cts.IsCancellationRequested) return;
+                                                        X2D1NoXlNoParlPosDto x2D1 = new X2D1NoXlNoParlPosDto()
+                                                        {
+                                                            TaskID = dto.ID,
+                                                            SigTime = minfo.CapTime.AddSeconds(data1[i].Smpstart / minfo.FsHz),
+                                                            MainCode = minfo.SatId,
+                                                            AdjaCode = ninfo.SatId,
+                                                            XdDfo = data2[i].Df,
+                                                            XdSnr = data2[i].Snr,
+                                                            SatTxLon = dto.CapLon,
+                                                            SatTxLat = dto.CapLat,
+                                                            CdbTxLon = dto.CapLon,
+                                                            CdbTxLat = dto.CapLat,
+                                                            FreqDown = minfo.FreqHz,
+                                                            FreqUp = dinfo.FreqHz,
+                                                            CheckRes = new CheckResDto()
+                                                            {
+                                                                FileName = Path.GetFileName(dinfo.FilePath),
+                                                                ModRate = deteResp.data[i].ModRate,
+                                                                ModType = deteResp.data[i].ModType,
+                                                                SmpCount = deteResp.data[i].Length,
+                                                                SmpStart = deteResp.data[i].Start,
+                                                                UserName = deteResp.data[i].UserName,
+                                                                FfcHz = deteResp.data[i].FfcHz,
+                                                                Snr = deteResp.data[i].Snr,
+                                                                PosCheckType = deteResp.data[i].DmcType.GetEnumByDisplayName<EnumPosCheckTypeDto>(),
+                                                            }
+                                                        };
+                                                        if (data1[i].Snr > 0 && data2[i].Snr > 0)
+                                                        {
+                                                            //卫星转发某些频点可能有时延,无参定位由于不能抵消需要减去这个时延
+                                                            if (checkFileType == 0)
+                                                            {
+                                                                x2D1.SxDto = data1[i].Dt * posDtoFactor - data2[i].Dt * posDtoFactor - delay1.Value + delay2.Value;
+                                                                x2D1.SxDfo = data1[i].Df - data2[i].Df;
+                                                                x2D1.SxSnr = (data1[i].Snr + data2[i].Snr) / 2;
+                                                                x2D1.XdDto = data1[i].Dt * posDtoFactor - delay1.Value;
+                                                                x2D1.XdDfo = data1[i].Df;
+                                                                x2D1.XdSnr = data1[i].Snr;
+                                                            }
+                                                            else
+                                                            {
+                                                                x2D1.SxDto = data2[i].Dt * posDtoFactor - delay1.Value + delay2.Value;
+                                                                x2D1.SxDfo = data2[i].Df;
+                                                                x2D1.SxSnr = data2[i].Snr;
+                                                                x2D1.XdDto = data1[i].Dt * posDtoFactor - delay1.Value;
+                                                                x2D1.XdDfo = data1[i].Df;
+                                                                x2D1.XdSnr = data1[i].Snr;
+                                                            }
+                                                        }
+                                                        var result = await HttpHelper.PostRequestAsync<PosResDto>(baseUrl + "Pos/PosX2D1NoXlNoParAsync", x2D1);
+                                                        if (result.code != 200)
+                                                        {
+                                                            await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻时隙位置{data1[i].Smpstart}定位异常.{result.msg}");
+                                                        }
+                                                    }
+                                                    catch (Exception ex)
+                                                    {
+                                                        await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻时隙位置{data1[i].Smpstart}定位异常", ex);
+                                                    }
+                                                }
+                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻定位完成");
+                                            }
+                                            catch (TaskCanceledException)
+                                            {
+                                            }
+                                            catch (Exception ex)
+                                            {
+                                                if (ex.InnerException != null && ex.InnerException.GetType() == typeof(TaskCanceledException))
+                                                    await LogHelper.Warning($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻文件处理结束,用户手动终止", ex.InnerException);
+                                                else
+                                                    await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻文件处理异常", ex);
+                                                continue;
+                                            }
+
+                                        }
+                                    });
+                                    listTask.Add(task);
+                                }
+                                await Task.WhenAll(listTask);
+                                preTime = capTime;
+                            }
+                        }
+                        if (!hasFile || preTime.Minute == 59)
+                        {
+                            await LogHelper.Info($"【任务{dto.ID}】缺少{preTime:yyyyMMddHHmmss}时刻之后的采集文件,等待5秒...");
+                            //实时任务没有文件需要考虑跳转到下一个小时的目录
+                            var time = new DateTime(preTime.Year, preTime.Month, preTime.Day, preTime.Hour, 0, 0);
+                            var now = DateTime.Now;
+                            if ((int)(now - time).TotalHours != 0)
+                            {
+                                preTime = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0);
+                            }
+                            await Task.Delay(5000, cts.Token);
+                        }
+                        else
+                        {
+                            await LogHelper.Info($"【任务{dto.ID}】目录[{filesDir}]本次扫描的数据处理完成");
+                        }
+                    }
+                    catch (TaskCanceledException ex)
+                    {
+                        await LogHelper.Warning($"【任务{dto.ID}】目录[{filesDir}]中的数据处理结束,用户手动终止", ex);
+                        ResetTime(formatFlag, ref preTime);
+                    }
+                    catch (Exception ex)
+                    {
+                        await LogHelper.Error($"【任务{dto.ID}】目录[{filesDir}]中的数据处理出错,跳过此目录", ex);
+                        ResetTime(formatFlag, ref preTime);
+                    }
+                }
+                await StopTask(dto.ID, EnumTaskStopType.Properly, "数据处理完成,任务结束");
+            }, cts.Token);
+        }
+
+        //等待采集完成(根据文件字节大小判断是否完成,最多等待采集时长+5秒)
+        private async Task WaitFileEnd(int taskID, HistoryFile file, int capSeconds, CancellationTokenSource cts)
+        {
+            int idx = 0;
+            Stopwatch sw = new Stopwatch();
+            sw.Start();
+            while (true)
+            {
+                FileInfo s = new FileInfo(file.FilePath);
+                long fs = (long)file.FsHz;
+                var fileSize = fs * capSeconds * 4;
+                if (s.Length == fileSize)
+                {
+                    break;
+                }
+                if (idx == 0)
+                    await LogHelper.Info($"【任务{taskID}】等待[{file.CapTime:yyyyMMddHHmmss}]时刻文件采集完成...");
+                await Task.Delay(2000, cts.Token);
+                if (sw.ElapsedMilliseconds / 1000 > capSeconds + 5)
+                    break;
+                idx++;
+            }
+            sw.Stop();
+        }
+
+        private bool CanOpenFile(int taskID, HistoryFile file)
+        {
+            try
+            {
+                using (var fs = new FileStream(file.FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+                {
+                }
+                return true;
+            }
+            catch (Exception ex)
+            {
+                LogHelper.Error($"【任务{taskID}】文件[{file.FilePath}]尝试打开失败", ex).Wait(5000);
+                return false;
+            }
+        }
+        private void ResetTime(int formatFlag, ref DateTime time)
+        {
+            if (formatFlag == 0)
+            {
+                time = DateTime.MaxValue;
+            }
+            else if (formatFlag == 1)
+            {
+                var newTime = new DateTime(time.Year, time.Month, time.Day, 0, 0, 0);
+                time = newTime.AddHours(24);
+            }
+            else
+            {
+                var newTime = new DateTime(time.Year, time.Month, time.Day, time.Hour, 0, 0);
+                time = newTime.AddHours(1);
+            }
+        }
+        private HistoryFile FileToHistoryFile(X2D1TaskHandleDto dto, string filePath, DateTime preTime, bool canConnected, CancellationToken ct)
+        {
+            if (ct.IsCancellationRequested) return null;
+            //读取采集文件
+            //2024_01_31_10_01_51_000000000_ch11_-1__Nxx.xxxxxx_Exx.xxxxxx_xxxxx.xxxHz_xxx.xxxMHz_ch1_xd1.dat
+            HistoryFile historyFile = new HistoryFile();
+            historyFile.FilePath = filePath;
+            var fileName = Path.GetFileNameWithoutExtension(filePath);
+            var strs = fileName.Split(new string[] { "_", "MHz", "Hz", "ch", "xd" }, StringSplitOptions.RemoveEmptyEntries);
+
+            //采集时间
+            var datestr = string.Join("_", strs.Take(6));
+            DateTime dateTime;
+            bool istime = DateTime.TryParseExact(datestr, "yyyy_MM_dd_HH_mm_ss", null, DateTimeStyles.None, out dateTime);
+            if (!istime) return null;
+            if (dateTime <= preTime) return null;
+            historyFile.CapTime = dateTime;
+
+
+            //采集通道
+            var chstr = strs.Skip(strs.Length - 2).Take(1).First();
+            int.TryParse(chstr, out int ch);
+
+            //上行信号分组
+            var xdIndexstr = strs.Skip(strs.Length - 1).Take(1).First();
+            int.TryParse(xdIndexstr, out int xdIndex);
+
+            //采集频点
+            var freqstr = strs.Skip(strs.Length - 3).Take(1).First();
+            double freqMHz;
+            double.TryParse(freqstr, out freqMHz);
+
+            //采样率
+            var fsstr = strs.Skip(strs.Length - 4).Take(1).First();
+            double.TryParse(fsstr, out double fsHz);
+
+            historyFile.FreqHz = (long)((decimal)freqMHz * 1000000);
+            historyFile.Ch = ch;
+            historyFile.FsHz = fsHz;
+            historyFile.XdIndex = xdIndex;
+            if (!canConnected)
+            {
+                if (ch == 2)
+                    historyFile.SatId = dto.MainSatCode;
+                else if (ch == 3)
+                    historyFile.SatId = dto.AdjaSatCode;
+            }
+            else
+            {
+                if (ch == 2)
+                {
+                    if (canConnected)
+                        historyFile.SatId = GetSatId(historyFile.FreqHz / 1e6, dto.ID);
+                    if (historyFile.SatId == 0)
+                    {
+                        historyFile.SatId = dto.MainSatCode;
+                    }
+                }
+                else if (ch == 3)
+                {
+                    if (canConnected)
+                        historyFile.SatId = GetSatId(historyFile.FreqHz / 1e6, dto.ID);
+                    if (historyFile.SatId == 0)
+                    {
+                        historyFile.SatId = dto.AdjaSatCode;
+                    }
+                }
+            }
+
+
+            return historyFile;
+        }
+
+        private int GetSatId(double freqdownMHz, int taskID)
+        {
+            int satId = 0;
+            string sql = $"select 卫星ID from freguencysatid where 下行 = '{freqdownMHz}'and 洋区 = 'I' LIMIT 1";
+            try
+            {
+                var res = MySqlTools.ExecuteScalar(System.Data.CommandType.Text, sql);
+                if (res == null || res == DBNull.Value)
+                {
+                    //LogHelper.Warning($"下行频点{freqdownMHz}未能从MySql中找到对应的卫星编号.SQL={sql}");
+                }
+                else
+                {
+                    bool isInt = int.TryParse($"{res}", out satId);
+                    if (!isInt)
+                    {
+                        LogHelper.Error($"【任务{taskID}】卫星编号转换失败,obj={res}").Wait(5000);
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                LogHelper.Warning($"【任务{taskID}】下行频点{freqdownMHz}从MySQL中查询卫星编号异常.ConnectionString={System.Configuration.ConfigurationManager.ConnectionStrings["MySql"].ConnectionString}", ex).Wait(5000);
+            }
+            return satId;
+        }
+        private bool CanGetSatIdFromMySql(int taskID)
+        {
+            string sql = $"select 卫星ID from freguencysatid where 下行 = '{0}'and 洋区 = 'I' LIMIT 1";
+            try
+            {
+                var res = MySqlTools.ExecuteScalar(System.Data.CommandType.Text, sql);
+                return true;
+            }
+            catch
+            {
+                LogHelper.Warning($"【任务{taskID}】无法连接到MySql,将使用任务中的卫星编号").Wait(5000);
+                return false;
+            }
+        }
+        private async Task StopTask(int taskID, EnumTaskStopType type, string stopReason)
+        {
+            await Task.Delay(2000);
+            if (type == EnumTaskStopType.Properly)
+            {
+                await LogHelper.Info($"【任务{taskID}】{stopReason}");
+            }
+            else
+            {
+                await LogHelper.Error($"【任务{taskID}】{stopReason}");
+            }
+            TaskStopHandleDto stopDto = new TaskStopHandleDto() { ID = taskID, StopType = type, StopReason = stopReason };
+            var stopResp = await HttpHelper.PostRequestAsync(baseUrl + "Task/StopTask", stopDto);
+            if (stopResp.code != 200)
+            {
+                await LogHelper.Error($"【任务{taskID}】停止异常.{stopResp.msg}");
+            }
+            if (dicCts.ContainsKey(taskID))
+                dicCts.Remove(taskID);
+        }
+
+        /// <summary>
+        /// 停止任务
+        /// </summary>
+        public void Stop(int taskID)
+        {
+            if (!dicCts.ContainsKey(taskID)) return;
+            dicCts[taskID]?.Cancel();
+            dicCts.Remove(taskID);
+        }
+
+        private bool IsLocal(string file)
+        {
+            if (file.StartsWith("\\")) return false;
+            DirectoryInfo dir = new DirectoryInfo(file);
+            foreach (DriveInfo d in DriveInfo.GetDrives())
+            {
+                if (string.Compare(dir.Root.FullName, d.Name, StringComparison.OrdinalIgnoreCase) == 0) //[drweb86] Fix for different case.
+                {
+                    return (d.DriveType != DriveType.Network);
+                }
+            }
+            return false;
+        }
+        List<List<IGrouping<int, HistoryFile>>> SplitFreqFiles(IEnumerable<IGrouping<int, HistoryFile>> multFreqFiles)
+        {
+            var thread = threadCount;
+            if (thread <= 0)
+                thread = 1000;
+            var list = new List<List<IGrouping<int, HistoryFile>>>();
+            var count = multFreqFiles.Count();//10
+            var countPackage = count / thread;//2
+            if (countPackage == 0)
+                countPackage = 1;
+            for (int i = 0; i < thread; i++)//0-3
+            {
+                if (i * countPackage >= count) break;
+                list.Add(multFreqFiles.Skip(i * countPackage).Take(countPackage).ToList());
+            }
+            for (int i = 0; i < list.Count; i++)
+            {
+                if (thread * countPackage + i >= count) break;
+                list[i].AddRange(multFreqFiles.Skip(thread * countPackage + i).Take(1));
+            }
+            return list;
+
+        }
+    }
+}

+ 154 - 83
Service/X2D1TaskServer/Service/TaskService.cs

@@ -167,7 +167,10 @@ namespace X2D1TaskServer.Service
                         }
                         bool isLocal = IsLocal(filesDir);
                         List<IGrouping<DateTime, HistoryFile>> groups = null;
-                        groups = files.Select(f => FileToHistoryFile(dto, f, preTime, canConnected, cts.Token)).GroupBy(m => m.CapTime).OrderBy(m => m.Key).ToList();
+                        groups = files.Select(f => FileToHistoryFile(dto, f, preTime, canConnected, cts.Token))
+                            .Where(p => p != null)
+                            .GroupBy(m => m.CapTime)
+                            .OrderBy(m => m.Key).ToList();
                         if (cts.IsCancellationRequested) break;
                         foreach (var sameTimeFiles in groups)
                         {
@@ -236,8 +239,8 @@ namespace X2D1TaskServer.Service
                                             {
                                                 long size = 0;
                                                 await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻三路采集文件正在拉取到本地...");
-                                                Stopwatch sw2 = new Stopwatch();
-                                                sw2.Start();
+                                                Stopwatch sw22 = new Stopwatch();
+                                                sw22.Start();
                                                 localFile1 = $"wwwroot\\{Path.GetFileName(minfo.FilePath)}";
                                                 using (FileStream fs = new FileStream(localFile1, FileMode.Create))
                                                 {
@@ -288,9 +291,9 @@ namespace X2D1TaskServer.Service
 
                                                 }
 
-                                                sw2.Stop();
-                                                var spped = size / 1024d / 1024d / (sw2.ElapsedMilliseconds / 1000d);
-                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻三路采集文件拉取到本地完成,共耗时{sw2.ElapsedMilliseconds}ms,平均速率{spped:f2}MB/s");
+                                                sw22.Stop();
+                                                var spped = size / 1024d / 1024d / (sw22.ElapsedMilliseconds / 1000d);
+                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻三路采集文件拉取到本地完成,共耗时{sw22.ElapsedMilliseconds}ms,平均速率{spped:f2}MB/s");
                                             }
 
                                             string mainFile = await HttpHelper.UploadFileAsync(localFile1, baseUrl, token: cts.Token);//主星文件
@@ -330,13 +333,19 @@ namespace X2D1TaskServer.Service
                                                 await LogHelper.Warning($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],该服务不支持Normal类型信号");
                                                 continue;
                                             }
+                                            Stopwatch sw3 = new Stopwatch();
+                                            sw3.Start();
                                             var deteResp = await HttpHelper.PostRequestAsync<List<DetectResDto>>(baseUrl + "DetectCg/DetectCalc", detectDto, token: cts.Token);
                                             if (deteResp.code != 200)
                                             {
-                                                await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻信号检测出错.{deteResp.msg}");
+                                                if (deteResp.msg.Contains("超时"))
+                                                    await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻{deteResp.msg}");
+                                                else
+                                                    await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻信号检测出错.{deteResp.msg}");
                                                 continue;
                                             }
-                                            await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻{checkFileTypeStr}检测完成,共{deteResp.data.Count}个时隙");
+                                            sw3.Stop();
+                                            await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻{checkFileTypeStr}检测完成,共{deteResp.data.Count}个时隙,耗时{sw3.ElapsedMilliseconds}ms");
                                             var smps = deteResp.data.Select(m => new SmpPosition(m.Start, m.Length)).ToList();//怎么补0?
                                             var cgDto = new CpuCgMultiDto()
                                             {
@@ -355,13 +364,19 @@ namespace X2D1TaskServer.Service
                                                 cgDto.file1 = mainFile;
                                                 cgDto.file2 = cdbFile;
                                             }
+                                            Stopwatch sw2 = new Stopwatch();
+                                            sw2.Start();
                                             var result1 = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(baseUrl + "DetectCg/CpuCgMultiCalc", cgDto, token: cts.Token);
                                             if (result1.code != 200)
                                             {
-                                                await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星超短CPU参估出错.{result1.msg}");
+                                                if (result1.msg.Contains("超时"))
+                                                    await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星超短{result1.msg}");
+                                                else
+                                                    await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星超短CPU参估出错.{result1.msg}");
                                                 continue;
                                             }
-                                            await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星超短CPU参估完成.");
+                                            sw2.Stop();
+                                            await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星超短CPU参估完成,耗时{sw2.ElapsedMilliseconds}ms");
                                             cgDto = new CpuCgMultiDto()
                                             {
                                                 dtCenter = 260000,
@@ -380,19 +395,31 @@ namespace X2D1TaskServer.Service
                                                 cgDto.dtCenter = 0;
                                                 cgDto.dtRange = 50000;
                                             }
+                                            sw2.Restart();
                                             var result2 = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(baseUrl + "DetectCg/CpuCgMultiCalc", cgDto, token: cts.Token);
                                             if (result2.code != 200)
                                             {
                                                 if (checkFileType == 0)
-                                                    await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻邻星超短CPU参估出错.{result2.msg}");
+                                                {
+                                                    if (result2.msg.Contains("超时"))
+                                                        await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻邻星超短{result2.msg}");
+                                                    else
+                                                        await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻邻星超短CPU参估出错.{result2.msg}");
+                                                }
                                                 else
-                                                    await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星邻星CPU参估出错.{result2.msg}");
+                                                {
+                                                    if (result2.msg.Contains("超时"))
+                                                        await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星邻星{result2.msg}");
+                                                    else
+                                                        await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星邻星CPU参估出错.{result2.msg}");
+                                                }
                                                 continue;
                                             }
+                                            sw2.Stop();
                                             if (checkFileType == 0)
-                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻邻星超短CPU参估完成");
+                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻邻星超短CPU参估完成,耗时{sw2.ElapsedMilliseconds}ms");
                                             else
-                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星邻星CPU参估完成");
+                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星邻星CPU参估完成,耗时{sw2.ElapsedMilliseconds}ms");
                                             await HttpHelper.DeleteFileAsync(baseUrl, mainFile, adjaFile, cdbFile);
                                             var data1 = result1.data;
                                             var data2 = result2.data;
@@ -474,7 +501,7 @@ namespace X2D1TaskServer.Service
                                         catch (Exception ex)
                                         {
                                             if (ex.InnerException != null && ex.InnerException.GetType() == typeof(TaskCanceledException))
-                                                await LogHelper.Warning($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻文件处理结束,用户手动终止", ex.InnerException);
+                                                break;
                                             else
                                                 await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻文件处理异常", ex);
                                             continue;
@@ -634,7 +661,10 @@ namespace X2D1TaskServer.Service
                         if (cts.IsCancellationRequested) return;
                         List<IGrouping<DateTime, HistoryFile>> groups = null;
                         bool isLocal = IsLocal(filesDir);
-                        groups = files.Select(f => FileToHistoryFile(dto, f, preTime, canConnected, cts.Token)).Where(p => p != null).GroupBy(m => m.CapTime).OrderBy(m => m.Key).ToList();
+                        groups = files.Select(f => FileToHistoryFile(dto, f, preTime, canConnected, cts.Token))
+                            .Where(p => p != null)
+                            .GroupBy(m => m.CapTime)
+                            .OrderBy(m => m.Key).ToList();
                         if (cts.IsCancellationRequested) break;
                         bool hasFile = false;
                         if (groups.Any())
@@ -718,8 +748,8 @@ namespace X2D1TaskServer.Service
                                                 {
                                                     long size = 0;
                                                     await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻三路采集文件正在拉取到本地...");
-                                                    Stopwatch sw2 = new Stopwatch();
-                                                    sw2.Start();
+                                                    Stopwatch sw22 = new Stopwatch();
+                                                    sw22.Start();
                                                     localFile1 = $"wwwroot\\{Path.GetFileName(minfo.FilePath)}";
                                                     using (FileStream fs = new FileStream(localFile1, FileMode.Create))
                                                     {
@@ -768,9 +798,9 @@ namespace X2D1TaskServer.Service
                                                             }
                                                         }
                                                     }
-                                                    sw2.Stop();
-                                                    var spped = size / 1024d / 1024d / (sw2.ElapsedMilliseconds / 1000d);
-                                                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻三路采集文件拉取到本地完成,共耗时{sw2.ElapsedMilliseconds}ms,平均速率{spped:f2}MB/s");
+                                                    sw22.Stop();
+                                                    var spped = size / 1024d / 1024d / (sw22.ElapsedMilliseconds / 1000d);
+                                                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻三路采集文件拉取到本地完成,共耗时{sw22.ElapsedMilliseconds}ms,平均速率{spped:f2}MB/s");
                                                 }
                                                 string mainFile = await HttpHelper.UploadFileAsync(localFile1, baseUrl, token: cts.Token);//主星文件
                                                 string adjaFile = await HttpHelper.UploadFileAsync(localFile2, baseUrl, token: cts.Token);//邻星文件
@@ -808,13 +838,19 @@ namespace X2D1TaskServer.Service
                                                     await LogHelper.Warning($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],该服务不支持Normal类型信号");
                                                     continue;
                                                 }
+                                                Stopwatch sw3 = new Stopwatch();
+                                                sw3.Start();
                                                 var deteResp = await HttpHelper.PostRequestAsync<List<DetectResDto>>(baseUrl + "DetectCg/DetectCalc", detectDto, token: cts.Token);
                                                 if (deteResp.code != 200)
                                                 {
-                                                    await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻信号检测出错.{deteResp.msg}");
+                                                    if (deteResp.msg.Contains("超时"))
+                                                        await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻{deteResp.msg}");
+                                                    else
+                                                        await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻信号检测出错.{deteResp.msg}");
                                                     continue;
                                                 }
-                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻信号检测完成,共{deteResp.data.Count}个时隙");
+                                                sw3.Stop();
+                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻信号检测完成,共{deteResp.data.Count}个时隙,耗时{sw3.ElapsedMilliseconds}ms");
                                                 var smps = deteResp.data.Select(m => new SmpPosition(m.Start, m.Length)).ToList();//怎么补0?
                                                 var cgDto = new CpuCgMultiDto()
                                                 {
@@ -832,13 +868,19 @@ namespace X2D1TaskServer.Service
                                                     cgDto.file1 = mainFile;
                                                     cgDto.file2 = cdbFile;
                                                 }
+                                                Stopwatch sw2 = new Stopwatch();
+                                                sw2.Start();
                                                 var result1 = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(baseUrl + "DetectCg/CpuCgMultiCalc", cgDto, token: cts.Token);
                                                 if (result1.code != 200)
                                                 {
-                                                    await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星超短CPU参估出错.{result1.msg}");
+                                                    if (result1.msg.Contains("超时"))
+                                                        await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星超短{result1.msg}");
+                                                    else
+                                                        await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星超短CPU参估出错.{result1.msg}");
                                                     continue;
                                                 }
-                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星超短CPU参估完成.");
+                                                sw2.Stop();
+                                                await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星超短CPU参估完成,耗时{sw2.ElapsedMilliseconds}ms");
                                                 cgDto = new CpuCgMultiDto()
                                                 {
                                                     dtCenter = 260000,
@@ -857,19 +899,32 @@ namespace X2D1TaskServer.Service
                                                     cgDto.dtCenter = 0;
                                                     cgDto.dtRange = 50000;
                                                 }
+
+                                                sw2.Restart();
                                                 var result2 = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(baseUrl + "DetectCg/CpuCgMultiCalc", cgDto, token: cts.Token);
                                                 if (result2.code != 200)
                                                 {
                                                     if (checkFileType == 0)
-                                                        await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻邻星超短CPU参估出错.{result2.msg}");
+                                                    {
+                                                        if (result2.msg.Contains("超时"))
+                                                            await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻邻星超短{result2.msg}");
+                                                        else
+                                                            await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻邻星超短CPU参估出错.{result2.msg}");
+                                                    }
                                                     else
-                                                        await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星邻星CPU参估出错.{result2.msg}");
+                                                    {
+                                                        if (result2.msg.Contains("超时"))
+                                                            await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星邻星{result2.msg}");
+                                                        else
+                                                            await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星邻星CPU参估出错.{result2.msg}");
+                                                    }
                                                     continue;
                                                 }
+                                                sw2.Stop();
                                                 if (checkFileType == 0)
-                                                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻邻星超短CPU参估完成");
+                                                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻邻星超短CPU参估完成,耗时{sw2.ElapsedMilliseconds}ms");
                                                 else
-                                                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星邻星CPU参估完成");
+                                                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻主星邻星CPU参估完成,耗时{sw2.ElapsedMilliseconds}ms");
                                                 await HttpHelper.DeleteFileAsync(baseUrl, mainFile, adjaFile, cdbFile);
                                                 var data1 = result1.data;
                                                 var data2 = result2.data;
@@ -951,7 +1006,7 @@ namespace X2D1TaskServer.Service
                                             catch (Exception ex)
                                             {
                                                 if (ex.InnerException != null && ex.InnerException.GetType() == typeof(TaskCanceledException))
-                                                    await LogHelper.Warning($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻文件处理结束,用户手动终止", ex.InnerException);
+                                                    break;
                                                 else
                                                     await LogHelper.Error($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],{capTime:yyyyMMddHHmmss}时刻文件处理异常", ex);
                                                 continue;
@@ -1056,75 +1111,91 @@ namespace X2D1TaskServer.Service
         }
         private HistoryFile FileToHistoryFile(X2D1TaskHandleDto dto, string filePath, DateTime preTime, bool canConnected, CancellationToken ct)
         {
-            if (ct.IsCancellationRequested) return null;
-            //读取采集文件
-            //2024_01_31_10_01_51_000000000_ch11_-1__Nxx.xxxxxx_Exx.xxxxxx_xxxxx.xxxHz_xxx.xxxMHz_ch1_xd1.dat
-            HistoryFile historyFile = new HistoryFile();
-            historyFile.FilePath = filePath;
-            var fileName = Path.GetFileNameWithoutExtension(filePath);
-            var strs = fileName.Split(new string[] { "_", "MHz", "Hz", "ch", "xd" }, StringSplitOptions.RemoveEmptyEntries);
+            try
+            {
+                if (ct.IsCancellationRequested) return null;
+                //读取采集文件
+                //2024_01_31_10_01_51_000000000_ch11_-1__Nxx.xxxxxx_Exx.xxxxxx_xxxxx.xxxHz_xxx.xxxMHz_ch1_xd1.dat
+                HistoryFile historyFile = new HistoryFile();
+                historyFile.FilePath = filePath;
+                var fileName = Path.GetFileNameWithoutExtension(filePath);
+                var strs = fileName.Split(new string[] { "_", "MHz", "Hz", "ch", "xd" }, StringSplitOptions.RemoveEmptyEntries);
 
-            //采集时间
-            var datestr = string.Join("_", strs.Take(6));
-            DateTime dateTime;
-            bool istime = DateTime.TryParseExact(datestr, "yyyy_MM_dd_HH_mm_ss", null, DateTimeStyles.None, out dateTime);
-            if (!istime) return null;
-            if (dateTime <= preTime) return null;
-            historyFile.CapTime = dateTime;
+                //采集时间
+                var datestr = string.Join("_", strs.Take(6));
+                DateTime dateTime;
+                bool istime = DateTime.TryParseExact(datestr, "yyyy_MM_dd_HH_mm_ss", null, DateTimeStyles.None, out dateTime);
+                if (!istime)
+                {
+                    _ = LogHelper.Error($"文件[{Path.GetFileName(filePath)}]格式异常,解析时间信息出错");
+                    return null;
+                }
+                if (dateTime <= preTime)
+                {
+                    //已处理,跳过此文件
+                    return null;
+                }
+                historyFile.CapTime = dateTime;
 
 
-            //采集通道
-            var chstr = strs.Skip(strs.Length - 2).Take(1).First();
-            int.TryParse(chstr, out int ch);
+                //采集通道
+                var chstr = strs.Skip(strs.Length - 2).Take(1).First();
+                int.TryParse(chstr, out int ch);
 
-            //上行信号分组
-            var xdIndexstr = strs.Skip(strs.Length - 1).Take(1).First();
-            int.TryParse(xdIndexstr, out int xdIndex);
+                //上行信号分组
+                var xdIndexstr = strs.Skip(strs.Length - 1).Take(1).First();
+                int.TryParse(xdIndexstr, out int xdIndex);
 
-            //采集频点
-            var freqstr = strs.Skip(strs.Length - 3).Take(1).First();
-            double freqMHz;
-            double.TryParse(freqstr, out freqMHz);
+                //采集频点
+                var freqstr = strs.Skip(strs.Length - 3).Take(1).First();
+                double freqMHz;
+                double.TryParse(freqstr, out freqMHz);
 
-            //采样率
-            var fsstr = strs.Skip(strs.Length - 4).Take(1).First();
-            double.TryParse(fsstr, out double fsHz);
+                //采样率
+                var fsstr = strs.Skip(strs.Length - 4).Take(1).First();
+                double.TryParse(fsstr, out double fsHz);
 
-            historyFile.FreqHz = (long)((decimal)freqMHz * 1000000);
-            historyFile.Ch = ch;
-            historyFile.FsHz = fsHz;
-            historyFile.XdIndex = xdIndex;
-            if (!canConnected)
-            {
-                if (ch == 2)
-                    historyFile.SatId = dto.MainSatCode;
-                else if (ch == 3)
-                    historyFile.SatId = dto.AdjaSatCode;
-            }
-            else
-            {
-                if (ch == 2)
+                historyFile.FreqHz = (long)((decimal)freqMHz * 1000000);
+                historyFile.Ch = ch;
+                historyFile.FsHz = fsHz;
+                historyFile.XdIndex = xdIndex;
+                if (!canConnected)
                 {
-                    if (canConnected)
-                        historyFile.SatId = GetSatId(historyFile.FreqHz / 1e6, dto.ID);
-                    if (historyFile.SatId == 0)
-                    {
+                    if (ch == 2)
                         historyFile.SatId = dto.MainSatCode;
-                    }
+                    else if (ch == 3)
+                        historyFile.SatId = dto.AdjaSatCode;
                 }
-                else if (ch == 3)
+                else
                 {
-                    if (canConnected)
-                        historyFile.SatId = GetSatId(historyFile.FreqHz / 1e6, dto.ID);
-                    if (historyFile.SatId == 0)
+                    if (ch == 2)
                     {
-                        historyFile.SatId = dto.AdjaSatCode;
+                        if (canConnected)
+                            historyFile.SatId = GetSatId(historyFile.FreqHz / 1e6, dto.ID);
+                        if (historyFile.SatId == 0)
+                        {
+                            historyFile.SatId = dto.MainSatCode;
+                        }
+                    }
+                    else if (ch == 3)
+                    {
+                        if (canConnected)
+                            historyFile.SatId = GetSatId(historyFile.FreqHz / 1e6, dto.ID);
+                        if (historyFile.SatId == 0)
+                        {
+                            historyFile.SatId = dto.AdjaSatCode;
+                        }
                     }
                 }
-            }
 
 
-            return historyFile;
+                return historyFile;
+            }
+            catch (Exception ex)
+            {
+                _ = LogHelper.Error($"文件[{Path.GetFileName(filePath)}]名称格式异常,解析出错", ex);
+                return null;
+            }
         }
 
         private int GetSatId(double freqdownMHz, int taskID)

+ 92 - 47
XdCxRhDW.App/Controllers/DetectCgController.cs

@@ -26,11 +26,18 @@ namespace XdCxRhDW.App.Controllers
         [HttpPost]
         public async Task<AjaxResult<CpuCgResDto>> CpuCgCalc(CpuCgDto dto)
         {
-            var svr = ServerContext.Instance.GetRandomOne(EnumSvrType.CpuCgSvr);
-            dto.file1 = await HttpHelper.UploadFileAsync(GetLocalFile(dto.file1), svr.BaseHttpAddr, timeoutSeconds: dto.TimeoutSeconds);
-            dto.file2 = await HttpHelper.UploadFileAsync(GetLocalFile(dto.file2), svr.BaseHttpAddr, timeoutSeconds: dto.TimeoutSeconds);
-            var res = await HttpHelper.PostRequestAsync<CpuCgResDto>(svr.BaseHttpAddr + "CpuCg/Calc", dto, dto.TimeoutSeconds);
-            return res;
+            try
+            {
+                var svr = ServerContext.Instance.GetRandomOne(EnumSvrType.CpuCgSvr);
+                dto.file1 = await HttpHelper.UploadFileAsync(GetLocalFile(dto.file1), svr.BaseHttpAddr, timeoutSeconds: dto.TimeoutSeconds);
+                dto.file2 = await HttpHelper.UploadFileAsync(GetLocalFile(dto.file2), svr.BaseHttpAddr, timeoutSeconds: dto.TimeoutSeconds);
+                var res = await HttpHelper.PostRequestAsync<CpuCgResDto>(svr.BaseHttpAddr + "CpuCg/Calc", dto, dto.TimeoutSeconds);
+                return res;
+            }
+            catch (TaskCanceledException)
+            {
+                return Error<CpuCgResDto>($"CPU参估超时");
+            }
         }
 
         /// <summary>
@@ -41,11 +48,18 @@ namespace XdCxRhDW.App.Controllers
         [HttpPost]
         public async Task<AjaxResult<List<CpuCgResDto>>> CpuCgMultiCalc(CpuCgMultiDto dto)
         {
-            var svr = ServerContext.Instance.GetRandomOne(EnumSvrType.CpuCgSvr);
-            dto.file1 = await HttpHelper.UploadFileAsync(GetLocalFile(dto.file1), svr.BaseHttpAddr, timeoutSeconds: dto.TimeoutSeconds);
-            dto.file2 = await HttpHelper.UploadFileAsync(GetLocalFile(dto.file2), svr.BaseHttpAddr, timeoutSeconds: dto.TimeoutSeconds);
-            var res = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(svr.BaseHttpAddr + "CpuCg/MultiCalc", dto, dto.TimeoutSeconds);
-            return res;
+            try
+            {
+                var svr = ServerContext.Instance.GetRandomOne(EnumSvrType.CpuCgSvr);
+                dto.file1 = await HttpHelper.UploadFileAsync(GetLocalFile(dto.file1), svr.BaseHttpAddr, timeoutSeconds: dto.TimeoutSeconds);
+                dto.file2 = await HttpHelper.UploadFileAsync(GetLocalFile(dto.file2), svr.BaseHttpAddr, timeoutSeconds: dto.TimeoutSeconds);
+                var res = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(svr.BaseHttpAddr + "CpuCg/MultiCalc", dto, dto.TimeoutSeconds);
+                return res;
+            }
+            catch (TaskCanceledException)
+            {
+                return Error<List<CpuCgResDto>>($"CPU参估超时({dto.smpPositions.Count}个突发)");
+            }
         }
 
         /// <summary>
@@ -69,11 +83,18 @@ namespace XdCxRhDW.App.Controllers
         [HttpPost]
         public async Task<AjaxResult<List<GpuCgResponseDto>>> GpuCgCalc(GpuCgRequestDto dto)
         {
-            var svr = ServerContext.Instance.GetRandomOne(EnumSvrType.GpuCgSvr);
-            dto.file1 = await HttpHelper.UploadFileAsync(GetLocalFile(dto.file1), svr.BaseHttpAddr, timeoutSeconds: dto.TimeoutSeconds);
-            dto.file2 = await HttpHelper.UploadFileAsync(GetLocalFile(dto.file2), svr.BaseHttpAddr, timeoutSeconds: dto.TimeoutSeconds);
-            var res = await HttpHelper.PostRequestAsync<List<GpuCgResponseDto>>(svr.BaseHttpAddr + "GpuCg/Calc", dto, dto.TimeoutSeconds);
-            return res;
+            try
+            {
+                var svr = ServerContext.Instance.GetRandomOne(EnumSvrType.GpuCgSvr);
+                dto.file1 = await HttpHelper.UploadFileAsync(GetLocalFile(dto.file1), svr.BaseHttpAddr, timeoutSeconds: dto.TimeoutSeconds);
+                dto.file2 = await HttpHelper.UploadFileAsync(GetLocalFile(dto.file2), svr.BaseHttpAddr, timeoutSeconds: dto.TimeoutSeconds);
+                var res = await HttpHelper.PostRequestAsync<List<GpuCgResponseDto>>(svr.BaseHttpAddr + "GpuCg/Calc", dto, dto.TimeoutSeconds);
+                return res;
+            }
+            catch (TaskCanceledException)
+            {
+                return Error<List<GpuCgResponseDto>>($"GPU参估超时");
+            }
         }
 
         /// <summary>
@@ -84,31 +105,39 @@ namespace XdCxRhDW.App.Controllers
         [HttpPost]
         public async Task<AjaxResult<List<DetectResDto>>> DetectCalc(DetectDto dto)
         {
-            var svr = ServerContext.Instance.GetRandomOne(EnumSvrType.CheckSvr);
-            dto.file1 = await HttpHelper.UploadFileAsync(GetLocalFile(dto.file1), svr.BaseHttpAddr, timeoutSeconds: dto.TimeoutSeconds);
-            var res = await HttpHelper.PostRequestAsync<List<DetectResDto>>(svr.BaseHttpAddr + "Check/Calc", dto, dto.TimeoutSeconds);
-            if (dto.SigProc && res.data.Any())
+            try
             {
-                SignalProcDto procDto = new SignalProcDto()
-                {
-                    File = dto.file1,
-                    Fs = (long)dto.fsHz,
-                    Smps = res.data.Select(p => new SmpPosition() { smpStart = p.Start, smpCount = p.Length }).ToList(),
-                };
-                var procRes = await HttpHelper.PostRequestAsync<List<SignalProcResDto>>(svr.BaseHttpAddr + "Check/SignalProc", procDto);
-                if (procRes.data == null || res.data.Count != procRes.data.Count)
+                var svr = ServerContext.Instance.GetRandomOne(EnumSvrType.CheckSvr);
+                dto.file1 = await HttpHelper.UploadFileAsync(GetLocalFile(dto.file1), svr.BaseHttpAddr, timeoutSeconds: dto.TimeoutSeconds);
+                var res = await HttpHelper.PostRequestAsync<List<DetectResDto>>(svr.BaseHttpAddr + "Check/Calc", dto, dto.TimeoutSeconds);
+                if (dto.SigProc && res.data.Any())
                 {
-                    throw new Exception("信号识别结果个数和检测结果个数不一致");
-                }
-                for (int i = 0; i < res.data.Count; i++)
-                {
-                    res.data[i].ModRate = procRes.data[i].Rate;
-                    res.data[i].ModType = procRes.data[i].ModType.GetEnumDisplayName();
-                    res.data[i].FfcHz = procRes.data[i].Ffc;
-                    res.data[i].Snr = procRes.data[i].Snr;
+                    SignalProcDto procDto = new SignalProcDto()
+                    {
+                        File = dto.file1,
+                        Fs = (long)dto.fsHz,
+                        Smps = res.data.Select(p => new SmpPosition() { smpStart = p.Start, smpCount = p.Length }).ToList(),
+                    };
+                    var procRes = await HttpHelper.PostRequestAsync<List<SignalProcResDto>>(svr.BaseHttpAddr + "Check/SignalProc", procDto);
+                    if (procRes.data == null || res.data.Count != procRes.data.Count)
+                    {
+                        throw new Exception("信号识别结果个数和检测结果个数不一致");
+                    }
+                    for (int i = 0; i < res.data.Count; i++)
+                    {
+                        res.data[i].ModRate = procRes.data[i].Rate;
+                        res.data[i].ModType = procRes.data[i].ModType.GetEnumDisplayName();
+                        res.data[i].FfcHz = procRes.data[i].Ffc;
+                        res.data[i].Snr = procRes.data[i].Snr;
+                    }
                 }
+                return res;
             }
-            return res;
+            catch (TaskCanceledException)
+            {
+                return Error<List<DetectResDto>>($"信号检测超时");
+            }
+
         }
 
         /// <summary>
@@ -119,10 +148,18 @@ namespace XdCxRhDW.App.Controllers
         [HttpPost]
         public async Task<AjaxResult<List<SignalProcResDto>>> SignalProc(SignalProcDto dto)
         {
-            var svr = ServerContext.Instance.GetRandomOne(EnumSvrType.CheckSvr);
-            dto.File = await HttpHelper.UploadFileAsync(GetLocalFile(dto.File), svr.BaseHttpAddr);
-            var res = await HttpHelper.PostRequestAsync<List<SignalProcResDto>>(svr.BaseHttpAddr + "Check/SignalProc", dto);
-            return res;
+
+            try
+            {
+                var svr = ServerContext.Instance.GetRandomOne(EnumSvrType.CheckSvr);
+                dto.File = await HttpHelper.UploadFileAsync(GetLocalFile(dto.File), svr.BaseHttpAddr);
+                var res = await HttpHelper.PostRequestAsync<List<SignalProcResDto>>(svr.BaseHttpAddr + "Check/SignalProc", dto);
+                return res;
+            }
+            catch (TaskCanceledException)
+            {
+                return Error<List<SignalProcResDto>>($"信号识别超时");
+            }
         }
 
 
@@ -134,15 +171,23 @@ namespace XdCxRhDW.App.Controllers
         [HttpPost]
         public async Task<AjaxResult<SigFilterResponseDto>> SigFilterProc(SigFilterDto dto)
         {
-            if (dto.BandHz <= 0 || dto.BandHz > dto.FsHz)
+            try
             {
-                return new AjaxResult<SigFilterResponseDto>() { code = 200, data = new SigFilterResponseDto() { File = dto.File } };
+                if (dto.BandHz <= 0 || dto.BandHz > dto.FsHz)
+                {
+                    dto.BandHz = 25000;
+                    //return new AjaxResult<SigFilterResponseDto>() { code = 200, data = new SigFilterResponseDto() { File = dto.File } };
+                }
+                var svr = ServerContext.Instance.GetRandomOne(EnumSvrType.CheckSvr);
+                dto.File = await HttpHelper.UploadFileAsync(GetLocalFile(dto.File), svr.BaseHttpAddr);
+                var res = await HttpHelper.PostRequestAsync<SigFilterResponseDto>(svr.BaseHttpAddr + "Check/SigFilterProc", dto);
+                await HttpHelper.DownloadFileAsync(svr.BaseHttpAddr, res.data.File, GetLocalFile(res.data.File), dto.TimeoutSeconds);
+                return res;
+            }
+            catch (TaskCanceledException)
+            {
+                return Error<SigFilterResponseDto>($"信号滤波超时");
             }
-            var svr = ServerContext.Instance.GetRandomOne(EnumSvrType.CheckSvr);
-            dto.File = await HttpHelper.UploadFileAsync(GetLocalFile(dto.File), svr.BaseHttpAddr);
-            var res = await HttpHelper.PostRequestAsync<SigFilterResponseDto>(svr.BaseHttpAddr + "Check/SigFilterProc", dto);
-            await HttpHelper.DownloadFileAsync(svr.BaseHttpAddr, res.data.File, GetLocalFile(res.data.File), dto.TimeoutSeconds);
-            return res;
         }
 
         /// <summary>

+ 1 - 0
XdCxRhDW.App/EditForms/SigDelayEditor.Designer.cs

@@ -96,6 +96,7 @@
             // 
             // txtDelay
             // 
+            this.txtDelay.EditValue = "2235";
             this.txtDelay.Location = new System.Drawing.Point(22, 103);
             this.txtDelay.Name = "txtDelay";
             this.txtDelay.Properties.AllowNullInput = DevExpress.Utils.DefaultBoolean.True;

+ 23 - 21
XdCxRhDW.App/EditForms/SigEditor.Designer.cs

@@ -56,6 +56,7 @@
             this.txtSnr = new DevExpress.XtraEditors.ButtonEdit();
             this.txtFreqDown = new DevExpress.XtraEditors.ButtonEdit();
             this.txtFreqUp = new DevExpress.XtraEditors.ButtonEdit();
+            this.txtBandHz = new DevExpress.XtraEditors.ButtonEdit();
             this.Root = new DevExpress.XtraLayout.LayoutControlGroup();
             this.layoutControlItem2 = new DevExpress.XtraLayout.LayoutControlItem();
             this.layoutControlItem3 = new DevExpress.XtraLayout.LayoutControlItem();
@@ -63,15 +64,15 @@
             this.layoutControlItem5 = new DevExpress.XtraLayout.LayoutControlItem();
             this.layoutControlItem6 = new DevExpress.XtraLayout.LayoutControlItem();
             this.layoutControlItem1 = new DevExpress.XtraLayout.LayoutControlItem();
-            this.dxErrorProvider = new DevExpress.XtraEditors.DXErrorProvider.DXErrorProvider(this.components);
-            this.txtBandHz = new DevExpress.XtraEditors.ButtonEdit();
             this.layoutControlItem7 = new DevExpress.XtraLayout.LayoutControlItem();
+            this.dxErrorProvider = new DevExpress.XtraEditors.DXErrorProvider.DXErrorProvider(this.components);
             ((System.ComponentModel.ISupportInitialize)(this.layoutControl1)).BeginInit();
             this.layoutControl1.SuspendLayout();
             ((System.ComponentModel.ISupportInitialize)(this.txtSigType)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(this.txtSnr.Properties)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(this.txtFreqDown.Properties)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(this.txtFreqUp.Properties)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.txtBandHz.Properties)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(this.Root)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem2)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem3)).BeginInit();
@@ -79,9 +80,8 @@
             ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem5)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem6)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem1)).BeginInit();
-            ((System.ComponentModel.ISupportInitialize)(this.dxErrorProvider)).BeginInit();
-            ((System.ComponentModel.ISupportInitialize)(this.txtBandHz.Properties)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem7)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.dxErrorProvider)).BeginInit();
             this.SuspendLayout();
             // 
             // layoutControl1
@@ -136,6 +136,7 @@
             // 
             // txtSnr
             // 
+            this.txtSnr.EditValue = "15";
             this.txtSnr.Location = new System.Drawing.Point(22, 308);
             this.txtSnr.Name = "txtSnr";
             this.txtSnr.Properties.AllowNullInput = DevExpress.Utils.DefaultBoolean.True;
@@ -167,6 +168,18 @@
             this.txtFreqUp.StyleController = this.layoutControl1;
             this.txtFreqUp.TabIndex = 0;
             // 
+            // txtBandHz
+            // 
+            this.txtBandHz.EditValue = "25000";
+            this.txtBandHz.Location = new System.Drawing.Point(22, 254);
+            this.txtBandHz.Name = "txtBandHz";
+            this.txtBandHz.Properties.AllowNullInput = DevExpress.Utils.DefaultBoolean.True;
+            this.txtBandHz.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] {
+            new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Glyph, "Hz", -1, false, true, false, editorButtonImageOptions4, new DevExpress.Utils.KeyShortcut(System.Windows.Forms.Keys.None), serializableAppearanceObject13, serializableAppearanceObject14, serializableAppearanceObject15, serializableAppearanceObject16, "", null, null, DevExpress.Utils.ToolTipAnchor.Default)});
+            this.txtBandHz.Size = new System.Drawing.Size(205, 23);
+            this.txtBandHz.StyleController = this.layoutControl1;
+            this.txtBandHz.TabIndex = 4;
+            // 
             // Root
             // 
             this.Root.EnableIndentsWithoutBorders = DevExpress.Utils.DefaultBoolean.True;
@@ -267,21 +280,6 @@
             this.layoutControlItem1.TextLocation = DevExpress.Utils.Locations.Top;
             this.layoutControlItem1.TextSize = new System.Drawing.Size(48, 14);
             // 
-            // dxErrorProvider
-            // 
-            this.dxErrorProvider.ContainerControl = this;
-            // 
-            // txtBandHz
-            // 
-            this.txtBandHz.Location = new System.Drawing.Point(22, 254);
-            this.txtBandHz.Name = "txtBandHz";
-            this.txtBandHz.Properties.AllowNullInput = DevExpress.Utils.DefaultBoolean.True;
-            this.txtBandHz.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] {
-            new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Glyph, "Hz", -1, false, true, false, editorButtonImageOptions4, new DevExpress.Utils.KeyShortcut(System.Windows.Forms.Keys.None), serializableAppearanceObject13, serializableAppearanceObject14, serializableAppearanceObject15, serializableAppearanceObject16, "", null, null, DevExpress.Utils.ToolTipAnchor.Default)});
-            this.txtBandHz.Size = new System.Drawing.Size(205, 23);
-            this.txtBandHz.StyleController = this.layoutControl1;
-            this.txtBandHz.TabIndex = 4;
-            // 
             // layoutControlItem7
             // 
             this.layoutControlItem7.Control = this.txtBandHz;
@@ -298,6 +296,10 @@
             this.layoutControlItem7.TextLocation = DevExpress.Utils.Locations.Top;
             this.layoutControlItem7.TextSize = new System.Drawing.Size(48, 14);
             // 
+            // dxErrorProvider
+            // 
+            this.dxErrorProvider.ContainerControl = this;
+            // 
             // SigEditor
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F);
@@ -314,6 +316,7 @@
             ((System.ComponentModel.ISupportInitialize)(this.txtSnr.Properties)).EndInit();
             ((System.ComponentModel.ISupportInitialize)(this.txtFreqDown.Properties)).EndInit();
             ((System.ComponentModel.ISupportInitialize)(this.txtFreqUp.Properties)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.txtBandHz.Properties)).EndInit();
             ((System.ComponentModel.ISupportInitialize)(this.Root)).EndInit();
             ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem2)).EndInit();
             ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem3)).EndInit();
@@ -321,9 +324,8 @@
             ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem5)).EndInit();
             ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem6)).EndInit();
             ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem1)).EndInit();
-            ((System.ComponentModel.ISupportInitialize)(this.dxErrorProvider)).EndInit();
-            ((System.ComponentModel.ISupportInitialize)(this.txtBandHz.Properties)).EndInit();
             ((System.ComponentModel.ISupportInitialize)(this.layoutControlItem7)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.dxErrorProvider)).EndInit();
             this.ResumeLayout(false);
 
         }

+ 23 - 12
XdCxRhDW.App/UserControl/CtrlHome.cs

@@ -198,6 +198,7 @@ namespace XdCxRhDW.App.UserControl
             }
         }
         bool canQuery = true;
+        private DateTime lasetUpdateTime = DateTime.MinValue;
         private void OnPosAdd(ModelPosRes posRes)
         {
             var currentTask = gridView1.GetFocusedRow() as TaskInfo;
@@ -235,20 +236,27 @@ namespace XdCxRhDW.App.UserControl
                 }
                 var hours = Convert.ToInt32(txtTimeCho.EditValue);
                 var ds = this.gridHomePosRes.DataSource as List<ModelPosRes>;
-                ds.Insert(0, posRes);
-                var max = ds.Max(p => p.SigTime);
-                var removeItems = ds.Where(p => (max - p.SigTime).TotalHours > hours).ToList();
-                foreach (var item in removeItems)
+                List<ModelPosRes> removeItems = null;
+                lock (this)
                 {
-                    ds.Remove(item);
-                    mapControl1.DelPosItem(item, false);
+                    ds.Insert(0, posRes);
+                    var max = ds.Max(p => p.SigTime);
+                    removeItems = ds.Where(p => (max - p.SigTime).TotalHours > hours).ToList();
+                    foreach (var item in removeItems)
+                    {
+                        ds.Remove(item);
+                    }
                 }
-
-                this.Invoke(new Action(() =>
+                mapControl1.DelPosItem(removeItems);
+                mapControl1.AddPosItem(posRes);
+                if ((DateTime.Now - lasetUpdateTime).TotalSeconds > 5)
                 {
-                    gridView2.RefreshData();
-                    mapControl1.AddPosItem(posRes);
-                }));
+                    this.Invoke(new Action(() =>
+                    {
+                        gridView2.RefreshData();
+                    }));
+                    lasetUpdateTime = DateTime.Now;
+                }
             }
         }
         private async void GridView1_FocusedRowObjectChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedRowObjectChangedEventArgs e)
@@ -569,11 +577,14 @@ namespace XdCxRhDW.App.UserControl
                                 {
                                     FreqDown = item.SigInfo.FreqDown,
                                     FreqUp = item.SigInfo.FreqUp,
-                                    BandHz = item.SigInfo.Band,
                                     SigType = (EnumSigCheckTypeDto)item.SigInfo.SigType,
                                     Snr = item.SigInfo.Snr,
                                     TaskInfoID = item.TaskInfoID,
                                 };
+                                if (item.SigInfo.Band != null && item.SigInfo.Band > 0)
+                                    sigDto.BandHz = item.SigInfo.Band.Value;
+                                else
+                                    sigDto.BandHz = 25000;
                                 var sigDelay = await db.SigDelays.Where(p => p.SigInfoId == item.SigInfo.ID).ToListAsync();
 
                                 sigDto.SigDelay.AddRange(sigDelay.MapTo<List<SigDelayDto>>());

+ 1 - 1
XdCxRhDW.Entity/SigInfo.cs

@@ -32,7 +32,7 @@ namespace XdCxRhDW.Entity
 
 
         [Display(Name = "带宽(Hz)")]
-        public double Band { get; set; }
+        public double? Band { get; set; }
 
         [NotMapped]
         [Display(Name = "是否是固定站")]

+ 13 - 1
XdCxRhDW.Repostory/EFContext/RHDWContext.cs

@@ -1,13 +1,17 @@
 using SQLite.CodeFirst;
 using System;
+using System.Collections.Generic;
 using System.Data.Common;
 using System.Data.Entity;
 using System.Data.Entity.Core.Common;
+using System.Data.Entity.Infrastructure;
 using System.Data.Entity.Infrastructure.Interception;
 using System.Data.Entity.ModelConfiguration.Conventions;
+using System.Data.Entity.Validation;
 using System.Data.SQLite;
 using System.Data.SQLite.EF6;
 using System.IO;
+using System.Linq;
 using System.Text.RegularExpressions;
 using XdCxRhDW.Entity;
 
@@ -40,7 +44,15 @@ namespace XdCxRhDW.Repostory
         public RHDWContext() : base("DbCon") //配置使用的连接名
         {
         }
-
+        //protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
+        //{
+        //    var tables = this.Database.SqlQuery<string>("select name from sqlite_master where type='table' and  name not like 'sqlite%'").ToList();
+        //    return base.ValidateEntity(entityEntry, items);
+        //}
+        //protected override bool ShouldValidateEntity(DbEntityEntry entityEntry)
+        //{
+        //    return  base.ShouldValidateEntity(entityEntry);
+        //}
         protected override void OnModelCreating(DbModelBuilder modelBuilder)
         {
             this.Database.Log = msg =>