You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
using Mirle.Component.MPLC.DataBlocks; using Mirle.Component.MPLC.Interfaces; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks;
namespace Mirle.Component.MPLC.FileData { /// <summary>
/// 檔案讀取器
/// </summary>
public class FileReader : IMPLCProvider, IDisposable { /// <summary>
/// 建構式
/// </summary>
public FileReader() { } /// <summary>
/// 檔案集
/// </summary>
private readonly List<string> files = new List<string>(); /// <summary>
/// 建立快取任務
/// </summary>
private Task _createCacheTask; /// <summary>
///
/// </summary>
private CancellationTokenSource _cancellationTokenSource; /// <summary>
/// 資料區塊
/// </summary>
private readonly List<FileDataBlock> _dataBlocks = new List<FileDataBlock>(); /// <summary>
/// 原始資料
/// </summary>
protected ConcurrentDictionary<DateTime, RawRecord> _rawData = new ConcurrentDictionary<DateTime, RawRecord>(); /// <summary>
///
/// </summary>
public double CachingPercentage => (double)_rawData.Values.Count(r => r.IsCached) / _rawData.Count * 100; /// <summary>
///
/// </summary>
public DateTime CurrentRowTime { get; private set; } /// <summary>
///
/// </summary>
public bool IsConnected => true; /// <summary>
///
/// </summary>
/// <param name="newDataBlock"></param>
public void AddDataBlock(FileDataBlock newDataBlock) { _dataBlocks.Add(newDataBlock); } /// <summary>
///
/// </summary>
/// <returns></returns>
public IEnumerable<FileDataBlock> GetDataBlocks() { return _dataBlocks; } /// <summary>
///
/// </summary>
/// <param name="FileName"></param>
public void AddFile(string FileName) { WaitForCreateCacheTask(); files.Add(FileName); } /// <summary>
///
/// </summary>
public void ClearFile() { WaitForCreateCacheTask(); _rawData.Clear(); files.Clear(); } /// <summary>
///
/// </summary>
public void OpenFile() { WaitForCreateCacheTask(); foreach (string f in files) { try { string[] rows = System.IO.File.ReadAllLines(f); foreach (string row in rows) { var time = DateTime.ParseExact(row.Substring(row.IndexOf('[') + 1, 14), "HH:mm:ss.fffff", null); var rawRecord = CreateRawRecord(row.Substring(row.IndexOf(']') + 2)); _rawData.TryAdd(time, rawRecord); } } catch (Exception ex) { Debug.WriteLine($"{ex.Message}-{ex.StackTrace}"); } } _cancellationTokenSource = new CancellationTokenSource(); _createCacheTask = new Task(() => CreateCache(_cancellationTokenSource.Token)); _createCacheTask.Start(); } /// <summary>
///
/// </summary>
private void WaitForCreateCacheTask() { if (_createCacheTask != null && _createCacheTask.Status == TaskStatus.Running) { _cancellationTokenSource.Cancel(); _createCacheTask.Wait(1000); } } /// <summary>
///
/// </summary>
/// <param name="token"></param>
private void CreateCache(CancellationToken token) { try { ParallelOptions po = new ParallelOptions { CancellationToken = token, MaxDegreeOfParallelism = Environment.ProcessorCount }; Parallel.ForEach(_rawData.Values, po, (r) => { r.CreateCache(); }); } catch (Exception ex) { Debug.WriteLine($"{ex.Message}-{ex.StackTrace}"); } } /// <summary>
///
/// </summary>
/// <param name="rawString"></param>
/// <returns></returns>
protected virtual RawRecord CreateRawRecord(string rawString) { return new RawRecord(rawString); } /// <summary>
///
/// </summary>
/// <returns></returns>
public IEnumerable<DateTime> GetDateTimeIndexes() { return _rawData.Keys.OrderBy(k => k); } /// <summary>
///
/// </summary>
/// <param name="index"></param>
public void Refresh(int index) { try { foreach (FileDataBlock block in _dataBlocks) { try { var rawRecords = _rawData.OrderBy(r => r.Key).ToList(); var rawRecord = rawRecords[index]; CurrentRowTime = rawRecord.Key; byte[] newByteArray = rawRecord.Value.GetBlockByIndex(block.ColumnIndex); block.SetRawData(newByteArray); } catch (Exception ex) { Debug.WriteLine($"{ex.Message}-{ex.StackTrace}"); } } } catch (Exception ex) { Debug.WriteLine($"{ex.Message}-{ex.StackTrace}"); } } /// <summary>
///
/// </summary>
/// <param name="index"></param>
public void Refresh(DateTime index) { if (_rawData.TryGetValue(index, out var value)) { try { foreach (var block in _dataBlocks) { try { byte[] newByteArray = value.GetBlockByIndex(block.ColumnIndex); block.SetRawData(newByteArray); } catch (Exception ex) { Debug.WriteLine($"{ex.Message}-{ex.StackTrace}"); } } CurrentRowTime = index; } catch (Exception ex) { Debug.WriteLine($"{ex.Message}-{ex.StackTrace}"); } } } /// <summary>
///
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
public bool GetBit(string address) { foreach (var block in _dataBlocks) { if (block.TryGetBit(address, out bool value)) return value; } return false; } /// <summary>
///
/// </summary>
/// <param name="address"></param>
public void SetBitOn(string address) { return; } /// <summary>
///
/// </summary>
/// <param name="address"></param>
public void SetBitOff(string address) { return; } /// <summary>
///
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
public int ReadWord(string address) { foreach (var block in _dataBlocks) { if (block.TryGetWord(address, out int value)) return value; } return 0; } /// <summary>
///
/// </summary>
/// <param name="address"></param>
/// <param name="data"></param>
public void WriteWord(string address, int data) { return; } /// <summary>
///
/// </summary>
/// <param name="startAddress"></param>
/// <param name="length"></param>
/// <returns></returns>
public int[] ReadWords(string startAddress, int length) { foreach (var block in _dataBlocks) { if (block.TryGetWords(startAddress, out int[] data, length)) return data; } return new int[length]; } /// <summary>
///
/// </summary>
/// <param name="startAddress"></param>
/// <param name="data"></param>
public void WriteWords(string startAddress, int[] data) { return; } /// <summary>
///
/// </summary>
/// <returns></returns>
public FileDataViewer GetDataView() { return new FileDataViewer(this); } /// <summary>
///
/// </summary>
/// <param name="dateTimeIndex"></param>
/// <param name="blockColumnIndex"></param>
/// <returns></returns>
public byte[] GetRawDataByDateTimeIndex(DateTime dateTimeIndex, int blockColumnIndex) { if (_rawData.TryGetValue(dateTimeIndex, out var value)) return value.GetBlockByIndex(blockColumnIndex); return null; }
#region IDisposable Support
private bool disposedValue = false; // 偵測多餘的呼叫
/// <summary>
/// 釋放資源
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { _createCacheTask?.Dispose(); _cancellationTokenSource?.Dispose(); } disposedValue = true; } } /// <summary>
/// 建構式
/// </summary>
~FileReader() { Dispose(false); } /// <summary>
/// 釋放資源
/// </summary>
public void Dispose() { Dispose(true); GC.SuppressFinalize(this); }
#endregion
} }
|