|
|
@@ -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;
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|