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.

204 lines
5.9 KiB

8 months ago
  1. using Mirle.Component.MPLC.DataBlocks;
  2. using Mirle.Component.MPLC.DataBlocks.Interfaces;
  3. using System;
  4. using System.Collections.Generic;
  5. namespace Mirle.Component.MPLC.SharedMemory
  6. {
  7. /// <summary>
  8. /// 共享記憶體快取讀取
  9. /// </summary>
  10. public class SMReadOnlyCachedReader : SMReadWriter, IDisposable
  11. {
  12. /// <summary>
  13. /// 建構式
  14. /// </summary>
  15. public SMReadOnlyCachedReader()
  16. {
  17. _cacheWorker = new ThreadWorker(CacheProc, 200);
  18. }
  19. /// <summary>
  20. /// 快取區塊對應
  21. /// </summary>
  22. private class CacheBlockMapping
  23. {
  24. /// <summary>
  25. /// 來源區塊
  26. /// </summary>
  27. public IDataBlock SourceBlock { get; set; }
  28. /// <summary>
  29. /// 快取區塊
  30. /// </summary>
  31. public IDataBlock CacheBlock { get; set; }
  32. }
  33. /// <summary>
  34. /// 快取區塊對應
  35. /// </summary>
  36. private readonly List<CacheBlockMapping> _cacheBlockMappings = new List<CacheBlockMapping>();
  37. /// <summary>
  38. /// 快取區塊
  39. /// </summary>
  40. private readonly List<DataBlock> _cachedBlocks = new List<DataBlock>();
  41. /// <summary>
  42. /// 快取執行續
  43. /// </summary>
  44. private readonly ThreadWorker _cacheWorker;
  45. /// <summary>
  46. /// 時間間隔
  47. /// </summary>
  48. public int Interval
  49. {
  50. get => _cacheWorker.Interval;
  51. set => _cacheWorker.Interval = value;
  52. }
  53. /// <summary>
  54. /// 快取處理
  55. /// </summary>
  56. private void CacheProc()
  57. {
  58. foreach (CacheBlockMapping cacheBlockMapping in _cacheBlockMappings)
  59. {
  60. cacheBlockMapping.CacheBlock.SetRawData(cacheBlockMapping.SourceBlock.GetRawData());
  61. }
  62. }
  63. /// <summary>
  64. /// 開始
  65. /// </summary>
  66. public void Start()
  67. {
  68. _cacheWorker.Start();
  69. }
  70. /// <summary>
  71. /// 新增資料區塊
  72. /// </summary>
  73. /// <param name="newDataBlock">資料區塊</param>
  74. public override void AddDataBlock(SMDataBlock newDataBlock)
  75. {
  76. _dataBlocks.Add(newDataBlock);
  77. DataBlock cacheBlock = new DataBlock(newDataBlock.DeviceRange);
  78. _cachedBlocks.Add(cacheBlock);
  79. _cacheBlockMappings.Add(new CacheBlockMapping()
  80. {
  81. SourceBlock = newDataBlock,
  82. CacheBlock = cacheBlock,
  83. });
  84. }
  85. /// <summary>
  86. /// 取得位元
  87. /// </summary>
  88. /// <param name="address">位置</param>
  89. /// <returns>True/False</returns>
  90. public override bool GetBit(string address)
  91. {
  92. foreach (DataBlock block in _cachedBlocks)
  93. {
  94. if (block.TryGetBit(address, out bool value))
  95. return value;
  96. }
  97. return false;
  98. }
  99. /// <summary>
  100. /// 設置位元開啟
  101. /// </summary>
  102. /// <param name="address">位置</param>
  103. public override void SetBitOn(string address)
  104. {
  105. return;
  106. }
  107. /// <summary>
  108. /// 設置位元關閉
  109. /// </summary>
  110. /// <param name="address">位置</param>
  111. public override void SetBitOff(string address)
  112. {
  113. return;
  114. }
  115. /// <summary>
  116. /// 讀取字元
  117. /// </summary>
  118. /// <param name="address">位置</param>
  119. /// <returns></returns>
  120. public override int ReadWord(string address)
  121. {
  122. foreach (DataBlock block in _cachedBlocks)
  123. {
  124. if (block.TryGetWord(address, out int value))
  125. return value;
  126. }
  127. return 0;
  128. }
  129. /// <summary>
  130. /// 寫入字元
  131. /// </summary>
  132. /// <param name="address">位置</param>
  133. /// <param name="data">位元</param>
  134. public override void WriteWord(string address, int data)
  135. {
  136. return;
  137. }
  138. /// <summary>
  139. /// 讀取多個字元
  140. /// </summary>
  141. /// <param name="startAddress">起始位置</param>
  142. /// <param name="length">長度</param>
  143. /// <returns>字元陣列</returns>
  144. public override int[] ReadWords(string startAddress, int length)
  145. {
  146. foreach (DataBlock block in _cachedBlocks)
  147. {
  148. if (block.TryGetWords(startAddress, out int[] data, length))
  149. return data;
  150. }
  151. return new int[length];
  152. }
  153. /// <summary>
  154. /// 寫入多個字元
  155. /// </summary>
  156. /// <param name="startAddress">起始位置</param>
  157. /// <param name="data">字元陣列</param>
  158. public override void WriteWords(string startAddress, int[] data)
  159. {
  160. return;
  161. }
  162. #region IDisposable Support
  163. private bool disposedValue = false; // 偵測多餘的呼叫
  164. /// <summary>
  165. /// 釋放資源
  166. /// </summary>
  167. /// <param name="disposing"></param>
  168. protected virtual void Dispose(bool disposing)
  169. {
  170. if (!disposedValue)
  171. {
  172. if (disposing)
  173. {
  174. if (_cacheWorker != null)
  175. {
  176. _cacheWorker.Pause();
  177. _cacheWorker.Dispose();
  178. }
  179. }
  180. disposedValue = true;
  181. }
  182. }
  183. /// <summary>
  184. /// 解構式
  185. /// </summary>
  186. ~SMReadOnlyCachedReader()
  187. {
  188. Dispose(false);
  189. }
  190. /// <summary>
  191. /// 釋放資源
  192. /// </summary>
  193. public void Dispose()
  194. {
  195. Dispose(true);
  196. GC.SuppressFinalize(this);
  197. }
  198. #endregion
  199. }
  200. }