更改了DataView数据查询的程序结构,继续调试。。。
This commit is contained in:
parent
2d5570c2e9
commit
18e5585cc7
|
@ -5,6 +5,7 @@ using System.Diagnostics;
|
|||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Configuration;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -209,8 +210,46 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
|
|||
VisibleRangeTime = new DateRange(StartDateTime.AddMinutes(-5), EndDateTime.AddMinutes(5));
|
||||
ChartAutoRange = AutoRange.Always;
|
||||
|
||||
var colorRandom = new Random();
|
||||
var colorPattern = GetNewColorPatternQueue();
|
||||
|
||||
// 生成待显示的数据列表
|
||||
SelectedData.Clear();
|
||||
|
||||
#region 生成曲线对象
|
||||
|
||||
foreach (var module in selectedModules)
|
||||
{
|
||||
var selectedTerminal = module.Flatten(true).Where(x => x.Selected == true);
|
||||
|
||||
foreach (var terminal in selectedTerminal)
|
||||
{
|
||||
var line2D = new SicFastLineSeries(terminal.FullName)
|
||||
{
|
||||
AntiAliasing = true,
|
||||
ResamplingMode = ResamplingMode.MinMax
|
||||
};
|
||||
|
||||
// 确保当列队未空时不会出错,选择默认黑色。
|
||||
var color = colorPattern.Any()
|
||||
? colorPattern.Dequeue()
|
||||
: Color.FromArgb(255, colorRandom.Next(0, 255), colorRandom.Next(0, 255),
|
||||
colorRandom.Next(0, 255));
|
||||
|
||||
line2D.Stroke = System.Windows.Media.Color.FromRgb(color.R, color.G, color.B);
|
||||
|
||||
var ds = line2D.GetDataSeries();
|
||||
ds.Tag = terminal;
|
||||
|
||||
|
||||
SelectedData.Add(line2D);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
var dataSeriesList = SelectedData.Select(x => x.DataSeries).ToList();
|
||||
|
||||
BusyIndicatorContent = "Querying Data ...";
|
||||
IsBusy = true;
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
|
@ -221,14 +260,14 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
|
|||
var ts = EndDateTime - StartDateTime;
|
||||
if (ts.Days <= 1)
|
||||
{
|
||||
await Query(selectedModules, StartDateTime, EndDateTime, _cancellationTokenSource);
|
||||
Query(selectedModules, dataSeriesList, StartDateTime, EndDateTime, _cancellationTokenSource);
|
||||
}
|
||||
else
|
||||
{
|
||||
var daySlices = Core.DateRange.SplitInToDays(new Core.DateRange(StartDateTime, EndDateTime));
|
||||
foreach (var range in daySlices)
|
||||
{
|
||||
await Query(selectedModules, range.Start, range.End, _cancellationTokenSource);
|
||||
Query(selectedModules, dataSeriesList, range.Start, range.End, _cancellationTokenSource);
|
||||
|
||||
if (_cancellationTokenSource.Token.IsCancellationRequested)
|
||||
break;
|
||||
|
@ -257,7 +296,7 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
|
|||
/// <summary>
|
||||
/// 查询数据
|
||||
/// </summary>
|
||||
public async Task Query(IEnumerable<ParameterNode> selectedModules, DateTime startTime, DateTime endTime,
|
||||
public void Query(IEnumerable<ParameterNode> selectedModules, List<IDataSeries> dataSeriesList, DateTime startTime, DateTime endTime,
|
||||
CancellationTokenSource cancellation)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
|
@ -267,7 +306,7 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
|
|||
Debug.WriteLine("start to query data ....");
|
||||
sw.Start();
|
||||
#endif
|
||||
var ds = await SearchDataBaseAsync(selectedModules, startTime, endTime, cancellation);
|
||||
var ds = SearchDataBaseAsync(selectedModules, startTime, endTime, cancellation);
|
||||
#if DEBUG
|
||||
sw.Stop();
|
||||
Debug.WriteLine($"Data returned, costs {sw.ElapsedMilliseconds}ms....");
|
||||
|
@ -288,7 +327,8 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
|
|||
Debug.WriteLine("start to render data ....");
|
||||
sw.Restart();
|
||||
#endif
|
||||
await RenderChartAndTable(ds, cancellation);
|
||||
var t = RenderChartAndTable(ds, cancellation, dataSeriesList);
|
||||
Task.WaitAll(t.ToArray());
|
||||
#if DEBUG
|
||||
sw.Stop();
|
||||
Debug.WriteLine($"Data render done, costs {sw.ElapsedMilliseconds}ms....");
|
||||
|
@ -331,83 +371,80 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
|
|||
/// 根据左侧选项查询数据
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task<DataSet> SearchDataBaseAsync(IEnumerable<ParameterNode> modules, DateTime startTime, DateTime endTime, CancellationTokenSource cancellation)
|
||||
private DataSet SearchDataBaseAsync(IEnumerable<ParameterNode> modules, DateTime startTime, DateTime endTime,
|
||||
CancellationTokenSource cancellation)
|
||||
{
|
||||
if (cancellation == null)
|
||||
throw new ArgumentNullException(nameof(cancellation), "cancellation object can not be null.");
|
||||
|
||||
var ds = new DataSet();
|
||||
|
||||
return await Task.Run(() =>
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
using (cancellation.Token.Register(Thread.CurrentThread.Abort))
|
||||
{
|
||||
using (cancellation.Token.Register(Thread.CurrentThread.Abort))
|
||||
// 遍历模组
|
||||
foreach (var module in modules)
|
||||
{
|
||||
// 遍历模组
|
||||
foreach (var module in modules)
|
||||
var sql = new StringBuilder();
|
||||
//! 因为数据库中按天拆表,无法一次性查询数据,需使用UNION合并多表查询,因此此处按天拼接SQL表达式
|
||||
// 最终SQL表达式结构为:
|
||||
// (select xx from date1.xx) union (select xx from date2.xx) union (select xx from date3.xx)
|
||||
// where time between xxx and xxx
|
||||
// order by time asc
|
||||
var ts = endTime - startTime;
|
||||
for (var day = 0; day <= ts.Days; day++)
|
||||
{
|
||||
var sql = new StringBuilder();
|
||||
//! 因为数据库中按天拆表,无法一次性查询数据,需使用UNION合并多表查询,因此此处按天拼接SQL表达式
|
||||
// 最终SQL表达式结构为:
|
||||
// (select xx from date1.xx) union (select xx from date2.xx) union (select xx from date3.xx)
|
||||
// where time between xxx and xxx
|
||||
// order by time asc
|
||||
var ts = endTime - startTime;
|
||||
for (var day = 0; day <= ts.Days; day++)
|
||||
// 检查表名是否存在,否则SQL执行出错。
|
||||
var tblName = $"{startTime.AddDays(day):yyyyMMdd}.{module}";
|
||||
if (CheckTableExists(tblName))
|
||||
{
|
||||
// 检查表名是否存在,否则SQL执行出错。
|
||||
var tblName = $"{startTime.AddDays(day):yyyyMMdd}.{module}";
|
||||
if (CheckTableExists(tblName))
|
||||
|
||||
sql.Append("select \"time\" AS InternalTimeStamp");
|
||||
var selectedParams = module.ChildNodes.FlattenNodes(true)
|
||||
.Where(x => x.Selected == true);
|
||||
|
||||
// 添加待查询的列
|
||||
foreach (var item in selectedParams)
|
||||
{
|
||||
|
||||
sql.Append("select \"time\" AS InternalTimeStamp");
|
||||
var selectedParams = module.ChildNodes.FlattenNodes(true)
|
||||
.Where(x => x.Selected == true);
|
||||
|
||||
// 添加待查询的列
|
||||
foreach (var item in selectedParams)
|
||||
{
|
||||
sql.Append("," + $"\"{item}\"");
|
||||
}
|
||||
|
||||
sql.Append($" from \"{tblName}\" ");
|
||||
|
||||
if (day < ts.Days)
|
||||
sql.Append(" UNION ");
|
||||
sql.Append("," + $"\"{item}\"");
|
||||
}
|
||||
|
||||
sql.Append($" from \"{tblName}\" ");
|
||||
|
||||
if (day < ts.Days)
|
||||
sql.Append(" UNION ");
|
||||
}
|
||||
|
||||
// 所有表名不可用,可能是日期范围错误
|
||||
if (sql.Length <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sql.Append(
|
||||
$" where \"time\" between {startTime.Ticks} and {endTime.Ticks} order by InternalTimeStamp asc");
|
||||
|
||||
// 查询数据并将返回的结果存储在DataSet中
|
||||
var dataTable = QueryDataClient.Instance.Service.QueryData(sql.ToString());
|
||||
|
||||
//! 返回的 DataTable 可能不存在,原因是上述代码自动生成的表明可能不存在。
|
||||
if (dataTable == null)
|
||||
continue;
|
||||
dataTable.TableName = module.Name;
|
||||
ds.Tables.Add(dataTable);
|
||||
}
|
||||
|
||||
// 所有表名不可用,可能是日期范围错误
|
||||
if (sql.Length <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sql.Append(
|
||||
$" where \"time\" between {startTime.Ticks} and {endTime.Ticks} order by InternalTimeStamp asc");
|
||||
|
||||
// 查询数据并将返回的结果存储在DataSet中
|
||||
var dataTable = QueryDataClient.Instance.Service.QueryData(sql.ToString());
|
||||
|
||||
//! 返回的 DataTable 可能不存在,原因是上述代码自动生成的表明可能不存在。
|
||||
if (dataTable == null)
|
||||
continue;
|
||||
dataTable.TableName = module.Name;
|
||||
ds.Tables.Add(dataTable);
|
||||
}
|
||||
}
|
||||
catch (ThreadAbortException)
|
||||
{
|
||||
// 操作被取消
|
||||
ds = null;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch (ThreadAbortException)
|
||||
{
|
||||
// 操作被取消
|
||||
ds = null;
|
||||
throw;
|
||||
}
|
||||
|
||||
return ds;
|
||||
|
||||
}, cancellation.Token);
|
||||
return ds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -415,7 +452,7 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
|
|||
/// </summary>
|
||||
/// <param name="ds"></param>
|
||||
/// <exception cref="Exception"></exception>
|
||||
private async Task RenderChartAndTable(DataSet ds, CancellationTokenSource cancellation)
|
||||
private List<Task> RenderChartAndTable(DataSet ds, CancellationTokenSource cancellation, List<IDataSeries> dataSeriesList)
|
||||
{
|
||||
if (cancellation == null)
|
||||
throw new ArgumentNullException(nameof(cancellation), "cancellation object can not be null.");
|
||||
|
@ -429,10 +466,10 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
|
|||
|
||||
var appendTask = new List<Task>();
|
||||
|
||||
var colorRandom = new Random();
|
||||
var colorPattern = GetNewColorPatternQueue();
|
||||
/*var colorRandom = new Random();
|
||||
var colorPattern = GetNewColorPatternQueue();*/
|
||||
|
||||
// 当曲线的数据点添加完毕时属性统计值。
|
||||
/*// 当曲线的数据点添加完毕时属性统计值。
|
||||
IProgress<XyDataSeries<DateTime, double>> seriesAppendDone = new Progress<XyDataSeries<DateTime, double>>(series =>
|
||||
{
|
||||
if (series.Tag is ParameterNode node)
|
||||
|
@ -441,7 +478,7 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
|
|||
node.MaxValue = node.RawData.Max(x => x.Value).ToString("F2");
|
||||
node.AverageValue = node.RawData.Average(x => x.Value).ToString("F2");
|
||||
}
|
||||
});
|
||||
});*/
|
||||
|
||||
// 一个Table一个模组
|
||||
foreach (var table in ds.Tables.Cast<DataTable>())
|
||||
|
@ -458,22 +495,24 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
|
|||
|
||||
var fullName = col.ColumnName;
|
||||
|
||||
// 在SelectedData中检查是否曲线已经存在,若不存在,新建一个
|
||||
/*// 在SelectedData中检查是否曲线已经存在,若不存在,新建一个
|
||||
var line2D = SelectedData.Cast<SicFastLineSeries>().FirstOrDefault(x => x.DataName == fullName);
|
||||
if (line2D == null)
|
||||
{
|
||||
line2D = new SicFastLineSeries(fullName)
|
||||
line2D = new SicFastLineSeries(fullName)
|
||||
{
|
||||
AntiAliasing = true,
|
||||
ResamplingMode = ResamplingMode.MinMax
|
||||
};
|
||||
|
||||
SelectedData.Add(line2D);
|
||||
SelectedData.Add(line2D);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 绑定LineChart对应的节点。
|
||||
var node = ParameterNodes.FindTerminalByFullName(fullName);
|
||||
|
||||
|
||||
// 确保当列队未空时不会出错,选择默认黑色。
|
||||
var color = colorPattern.Any()
|
||||
? colorPattern.Dequeue()
|
||||
|
@ -481,89 +520,110 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
|
|||
colorRandom.Next(0, 255));
|
||||
|
||||
line2D.Stroke = System.Windows.Media.Color.FromRgb(color.R, color.G, color.B);
|
||||
|
||||
var dataSeries = line2D.GetDataSeries();
|
||||
|
||||
var dataSeries = line2D.GetDataSeries();*/
|
||||
|
||||
var dataSeries =
|
||||
dataSeriesList.FirstOrDefault(x => (x.Tag is ParameterNode node) && node.FullName == fullName);
|
||||
|
||||
if (dataSeries == null)
|
||||
continue;
|
||||
|
||||
// ParameterNode放在line2D.DataSeries.Tag中,而不是line2D.Tag中,因为ParameterNode需要从Task中抛给seriesAppendDone
|
||||
/*// ParameterNode放在line2D.DataSeries.Tag中,而不是line2D.Tag中,因为ParameterNode需要从Task中抛给seriesAppendDone
|
||||
// 进行数据统计,但Task中无法访问line2D对象,因为跨线程访问问题。
|
||||
dataSeries.Tag = node;
|
||||
var rawData = node.RawData;
|
||||
dataSeries.Tag = node;*/
|
||||
var rawData = (dataSeries.Tag as ParameterNode)?.RawData;
|
||||
if(rawData == null)
|
||||
continue;
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#if DEBUG
|
||||
Debug.WriteLine($"[{sw.ElapsedMilliseconds}ms] Appending point to series {line2D.DataName} ...");
|
||||
Debug.WriteLine($"[{sw.ElapsedMilliseconds}ms] Appending point to series {fullName} ...");
|
||||
#endif
|
||||
|
||||
//using (dataSeries.SuspendUpdates())
|
||||
//{
|
||||
var t = Task.Run(() =>
|
||||
var t = Task.Run(() =>
|
||||
{
|
||||
#if DEBUG
|
||||
Debug.WriteLine(
|
||||
$"\t[{sw.ElapsedMilliseconds}ms] Start to appending data to {fullName} ...");
|
||||
#endif
|
||||
|
||||
// 限制LineChart.Points数量,提高显示速度。
|
||||
const int RESTRICT_POINTS_IN_SERIES = 1000;
|
||||
|
||||
var rows = table.Rows;
|
||||
var skippedRows = rows.Count / RESTRICT_POINTS_IN_SERIES;
|
||||
if (skippedRows <= 0)
|
||||
skippedRows = 1;
|
||||
|
||||
// 遍历数据行,添加数据点到LineChart。
|
||||
var skipped = 0;
|
||||
|
||||
var dateList = new List<DateTime>();
|
||||
var valueList = new List<double>();
|
||||
var metaList = new List<ParameterNodePoint>();
|
||||
|
||||
for (var i = 0; i < rows.Count; i++)
|
||||
{
|
||||
#if DEBUG
|
||||
Debug.WriteLine(
|
||||
$"\t[{sw.ElapsedMilliseconds}ms] Start to appending data to {line2D.DataName} ...");
|
||||
#endif
|
||||
var date = new DateTime(long.Parse(rows[i][0].ToString()));
|
||||
var cellValue = rows[i][col];
|
||||
var value = double.NaN;
|
||||
|
||||
// 限制LineChart.Points数量,提高显示速度。
|
||||
const int RESTRICT_POINTS_IN_SERIES = 1000;
|
||||
if (cellValue is bool b)
|
||||
value = b ? 1 : 0;
|
||||
else if (double.TryParse(cellValue.ToString(), out var num))
|
||||
value = num;
|
||||
else
|
||||
value = 0;
|
||||
|
||||
var rows = table.Rows;
|
||||
var skippedRows = rows.Count / RESTRICT_POINTS_IN_SERIES;
|
||||
if (skippedRows <= 0)
|
||||
skippedRows = 1;
|
||||
dateList.Add(date);
|
||||
valueList.Add(value);
|
||||
metaList.Add(new ParameterNodePoint(date, value));
|
||||
|
||||
// 遍历数据行,添加数据点到LineChart。
|
||||
var skipped = 0;
|
||||
for (var i = 0; i < rows.Count; i++)
|
||||
/*((XyDataSeries<DateTime, double>)dataSeries).Append(date, value, new ParameterNodePoint(date, value));
|
||||
rawData.Add(new ParameterNodePoint(date, value));*/
|
||||
|
||||
|
||||
/*// Re-sampling to improve the rendering performance.
|
||||
if (skipped >= skippedRows)
|
||||
{
|
||||
var date = new DateTime(long.Parse(rows[i][0].ToString()));
|
||||
var cellValue = rows[i][col];
|
||||
var value = double.NaN;
|
||||
|
||||
if (cellValue is bool b)
|
||||
value = b ? 1 : 0;
|
||||
else if (double.TryParse(cellValue.ToString(), out var num))
|
||||
value = num;
|
||||
else
|
||||
value = 0;
|
||||
|
||||
dataSeries.Append(date, value, new ParameterNodePoint(date, value));
|
||||
rawData.Add(new ParameterNodePoint(date, value));
|
||||
|
||||
|
||||
/*// Re-sampling to improve the rendering performance.
|
||||
if (skipped >= skippedRows)
|
||||
{
|
||||
dataSeries.Append(date, value, new ParameterNodePoint(date, value));
|
||||
skipped = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
skipped++;
|
||||
}*/
|
||||
|
||||
|
||||
// 操作被取消
|
||||
if (cancellation.Token.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
//Thread.Sleep(1);
|
||||
|
||||
|
||||
skipped = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
skipped++;
|
||||
}*/
|
||||
|
||||
//
|
||||
seriesAppendDone.Report(dataSeries);
|
||||
|
||||
// 操作被取消
|
||||
if (cancellation.Token.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
//Thread.Sleep(1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
//seriesAppendDone.Report(dataSeries);
|
||||
|
||||
using (dataSeries.SuspendUpdates())
|
||||
{
|
||||
((XyDataSeries<DateTime, double>)dataSeries).Append(dateList, valueList, metaList);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
Debug.WriteLine(
|
||||
$"\t[{sw.ElapsedMilliseconds}ms] Finish appending data to {line2D.DataName}!");
|
||||
$"\t[{sw.ElapsedMilliseconds}ms] Finish appending data to {fullName}!");
|
||||
#endif
|
||||
});
|
||||
});
|
||||
|
||||
appendTask.Add(t);
|
||||
appendTask.Add(t);
|
||||
//}
|
||||
|
||||
//await Task.Delay(100);
|
||||
|
@ -575,7 +635,7 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
|
|||
#endif
|
||||
|
||||
// 等待所有序列写入数据完成。
|
||||
await Task.WhenAll(appendTask);
|
||||
//await Task.WhenAll(appendTask);
|
||||
|
||||
//}
|
||||
|
||||
|
@ -585,6 +645,8 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
|
|||
Debug.WriteLine($"[{sw.ElapsedMilliseconds}ms] Method {nameof(RenderChartAndTable)} Done!");
|
||||
sw.Stop();
|
||||
#endif
|
||||
|
||||
return appendTask;
|
||||
}
|
||||
|
||||
#region Parameter Grid Control
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue