1
wanshenmean
2026-03-16 689dd676fc0efb31236d989334122590b7198d61
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
using System.Threading;
using WIDESEAWCS_S7Simulator.Core.Interfaces;
 
namespace WIDESEAWCS_S7Simulator.Core.Memory
{
    /// <summary>
    /// 内存区域基类
    /// </summary>
    public abstract class MemoryRegion : IMemoryRegion
    {
        /// <summary>
        /// 内存数据
        /// </summary>
        protected readonly byte[] _memory;
 
        /// <summary>
        /// 读写锁(支持并发访问)
        /// </summary>
        protected readonly ReaderWriterLockSlim _lock;
 
        /// <summary>
        /// 释放状态标志
        /// </summary>
        protected bool _disposed = false;
 
        /// <summary>
        /// 区域类型
        /// </summary>
        public abstract string RegionType { get; }
 
        /// <summary>
        /// 区域大小(字节)
        /// </summary>
        public int Size { get; }
 
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="size">区域大小</param>
        protected MemoryRegion(int size)
        {
            Size = size;
            _memory = new byte[size];
            _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
        }
 
        /// <summary>
        /// 读取字节数据
        /// </summary>
        public virtual byte[] Read(ushort offset, ushort length)
        {
            if (_disposed)
                throw new ObjectDisposedException(nameof(MemoryRegion));
 
            _lock.EnterReadLock();
            try
            {
                if (offset + length > Size)
                    throw new ArgumentOutOfRangeException(
                        $"读取超出{RegionType}区范围: offset={offset}, length={length}, size={Size}");
 
                byte[] result = new byte[length];
                Array.Copy(_memory, offset, result, 0, length);
                return result;
            }
            finally
            {
                _lock.ExitReadLock();
            }
        }
 
        /// <summary>
        /// 写入字节数据
        /// </summary>
        public virtual void Write(ushort offset, byte[] data)
        {
            if (_disposed)
                throw new ObjectDisposedException(nameof(MemoryRegion));
 
            if (data == null)
                throw new ArgumentNullException(nameof(data));
 
            _lock.EnterWriteLock();
            try
            {
                if (offset + data.Length > Size)
                    throw new ArgumentOutOfRangeException(
                        $"写入超出{RegionType}区范围: offset={offset}, length={data.Length}, size={Size}");
 
                Array.Copy(data, 0, _memory, offset, data.Length);
            }
            finally
            {
                _lock.ExitWriteLock();
            }
        }
 
        /// <summary>
        /// 清空区域
        /// </summary>
        public virtual void Clear()
        {
            if (_disposed)
                throw new ObjectDisposedException(nameof(MemoryRegion));
 
            _lock.EnterWriteLock();
            try
            {
                Array.Clear(_memory, 0, Size);
            }
            finally
            {
                _lock.ExitWriteLock();
            }
        }
 
        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
 
        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="disposing">是否正在释放托管资源</param>
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    _lock?.Dispose();
                }
                _disposed = true;
            }
        }
    }
}