线程安全的,网口控制仪器的程序(C#)

44 阅读4分钟

以下是完整实现:

csharp

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;

namespace InstrumentControl
{
    /// <summary>
    /// 仪器通信协议类型
    /// </summary>
    public enum InstrumentProtocol
    {
        TCP,
        UDP,
        RawSocket
    }

    /// <summary>
    /// 仪器控制异常
    /// </summary>
    public class InstrumentControlException : Exception
    {
        public InstrumentControlException(string message) : base(message) { }
        public InstrumentControlException(string message, Exception innerException) 
            : base(message, innerException) { }
    }

    /// <summary>
    /// 仪器响应数据
    /// </summary>
    public class InstrumentResponse
    {
        public bool IsSuccess { get; set; }
        public byte[] RawData { get; set; }
        public string Message { get; set; }
        public TimeSpan ResponseTime { get; set; }
        public DateTime Timestamp { get; set; }

        public string GetString(Encoding encoding = null)
        {
            encoding ??= Encoding.ASCII;
            return encoding.GetString(RawData);
        }
    }

    /// <summary>
    /// 仪器命令封装
    /// </summary>
    public class InstrumentCommand
    {
        public string Command { get; }
        public byte[] CommandBytes { get; }
        public TimeSpan Timeout { get; set; }
        public string ExpectedResponsePattern { get; set; }
        public TaskCompletionSource<InstrumentResponse> CompletionSource { get; }
        public DateTime QueuedTime { get; }
        public CancellationToken CancellationToken { get; }

        public InstrumentCommand(string command, TimeSpan timeout, 
            CancellationToken cancellationToken = default)
        {
            Command = command;
            CommandBytes = Encoding.ASCII.GetBytes(command);
            Timeout = timeout;
            QueuedTime = DateTime.UtcNow;
            CompletionSource = new TaskCompletionSource<InstrumentResponse>();
            CancellationToken = cancellationToken;
        }

        public InstrumentCommand(byte[] commandBytes, TimeSpan timeout,
            CancellationToken cancellationToken = default)
        {
            CommandBytes = commandBytes;
            Command = Encoding.ASCII.GetString(commandBytes);
            Timeout = timeout;
            QueuedTime = DateTime.UtcNow;
            CompletionSource = new TaskCompletionSource<InstrumentResponse>();
            CancellationToken = cancellationToken;
        }
    }

    /// <summary>
    /// 线程安全的网口仪器控制器
    /// </summary>
    public class NetworkInstrumentController : IDisposable
    {
        #region 私有字段
        private readonly object _connectionLock = new object();
        private readonly object _sendLock = new object();
        private readonly ConcurrentQueue<InstrumentCommand> _commandQueue = new ConcurrentQueue<InstrumentCommand>();
        private readonly SemaphoreSlim _queueSemaphore = new SemaphoreSlim(0);
        private readonly CancellationTokenSource _globalCancellationTokenSource = new CancellationTokenSource();
        private readonly ManualResetEventSlim _connectionEvent = new ManualResetEventSlim(false);
        
        private TcpClient _tcpClient;
        private UdpClient _udpClient;
        private NetworkStream _networkStream;
        private Task _processingTask;
        private volatile bool _isConnected = false;
        private volatile bool _isDisposed = false;
        
        // 配置参数
        private readonly string _host;
        private readonly int _port;
        private readonly InstrumentProtocol _protocol;
        private readonly TimeSpan _defaultTimeout;
        private readonly int _receiveBufferSize;
        private readonly Encoding _encoding;
        private readonly int _maxRetryCount;
        private readonly TimeSpan _reconnectInterval;
        
        // 统计信息
        private long _totalCommandsSent = 0;
        private long _failedCommands = 0;
        private DateTime _lastActivityTime;
        #endregion

        #region 公共属性
        public string InstrumentId { get; }
        public bool IsConnected => _isConnected && !_isDisposed;
        public string ConnectionString => $"{_protocol}://{_host}:{_port}";
        public DateTime LastActivityTime => _lastActivityTime;
        public long TotalCommandsSent => Interlocked.Read(ref _totalCommandsSent);
        public long FailedCommands => Interlocked.Read(ref _failedCommands);
        public double SuccessRate => TotalCommandsSent == 0 ? 100 : 
            (TotalCommandsSent - FailedCommands) * 100.0 / TotalCommandsSent;
        #endregion

        #region 事件
        public event EventHandler<InstrumentResponse> CommandCompleted;
        public event EventHandler<string> ConnectionStatusChanged;
        public event EventHandler<Exception> ErrorOccurred;
        #endregion

        #region 构造函数
        public NetworkInstrumentController(
            string instrumentId,
            string host,
            int port,
            InstrumentProtocol protocol = InstrumentProtocol.TCP,
            TimeSpan? defaultTimeout = null,
            int receiveBufferSize = 4096,
            Encoding encoding = null,
            int maxRetryCount = 3,
            TimeSpan? reconnectInterval = null)
        {
            if (string.IsNullOrWhiteSpace(instrumentId))
                throw new ArgumentException("Instrument ID cannot be empty", nameof(instrumentId));
            if (string.IsNullOrWhiteSpace(host))
                throw new ArgumentException("Host cannot be empty", nameof(host));
            if (port < 1 || port > 65535)
                throw new ArgumentException("Invalid port number", nameof(port));

            InstrumentId = instrumentId;
            _host = host;
            _port = port;
            _protocol = protocol;
            _defaultTimeout = defaultTimeout ?? TimeSpan.FromSeconds(5);
            _receiveBufferSize = receiveBufferSize;
            _encoding = encoding ?? Encoding.ASCII;
            _maxRetryCount = maxRetryCount;
            _reconnectInterval = reconnectInterval ?? TimeSpan.FromSeconds(2);

            Initialize();
        }
        #endregion

        #region 初始化
        private void Initialize()
        {
            _processingTask = Task.Run(async () => await ProcessCommandQueueAsync());
            _lastActivityTime = DateTime.UtcNow;
        }
        #endregion

        #region 连接管理
        /// <summary>
        /// 连接到仪器
        /// </summary>
        public async Task ConnectAsync(CancellationToken cancellationToken = default)
        {
            if (_isDisposed)
                throw new ObjectDisposedException(nameof(NetworkInstrumentController));

            lock (_connectionLock)
            {
                if (_isConnected)
                    return;

                OnConnectionStatusChanged($"正在连接仪器 {InstrumentId}...");
            }

            try
            {
                await InternalConnectAsync(cancellationToken).ConfigureAwait(false);
                
                lock (_connectionLock)
                {
                    _isConnected = true;
                    _connectionEvent.Set();
                }

                OnConnectionStatusChanged($"仪器 {InstrumentId} 连接成功");
            }
            catch (Exception ex)
            {
                OnErrorOccurred(ex);
                throw new InstrumentControlException($"连接仪器失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 内部连接方法
        /// </summary>
        private async Task InternalConnectAsync(CancellationToken cancellationToken)
        {
            switch (_protocol)
            {
                case InstrumentProtocol.TCP:
                    _tcpClient = new TcpClient();
                    await _tcpClient.ConnectAsync(_host, _port, cancellationToken).ConfigureAwait(false);
                    _tcpClient.ReceiveTimeout = (int)_defaultTimeout.TotalMilliseconds;
                    _tcpClient.SendTimeout = (int)_defaultTimeout.TotalMilliseconds;
                    _networkStream = _tcpClient.GetStream();
                    break;

                case InstrumentProtocol.UDP:
                    _udpClient = new UdpClient();
                    await _udpClient.ConnectAsync(_host, _port, cancellationToken).ConfigureAwait(false);
                    break;

                case InstrumentProtocol.RawSocket:
                    var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    await socket.ConnectAsync(_host, _port, cancellationToken).ConfigureAwait(false);
                    _tcpClient = new TcpClient { Client = socket };
                    _networkStream = new NetworkStream(socket, true);
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(_protocol));
            }
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        public async Task DisconnectAsync()
        {
            if (_isDisposed)
                return;

            lock (_connectionLock)
            {
                if (!_isConnected)
                    return;

                _isConnected = false;
                _connectionEvent.Reset();
                OnConnectionStatusChanged($"正在断开仪器 {InstrumentId} 连接...");
            }

            try
            {
                // 取消所有待处理命令
                while (_commandQueue.TryDequeue(out var command))
                {
                    command.CompletionSource.TrySetCanceled();
                }

                // 关闭连接
                switch (_protocol)
                {
                    case InstrumentProtocol.TCP:
                    case InstrumentProtocol.RawSocket:
                        _networkStream?.Close();
                        _tcpClient?.Close();
                        break;
                    case InstrumentProtocol.UDP:
                        _udpClient?.Close();
                        break;
                }
            }
            catch (Exception ex)
            {
                OnErrorOccurred(ex);
            }
            finally
            {
                _networkStream = null;
                _tcpClient = null;
                _udpClient = null;
                OnConnectionStatusChanged($"仪器 {InstrumentId} 已断开连接");
            }
        }

        /// <summary>
        /// 确保连接
        /// </summary>
        private async Task EnsureConnectedAsync(CancellationToken cancellationToken)
        {
            if (!_isConnected)
            {
                await ConnectAsync(cancellationToken).ConfigureAwait(false);
            }

            // 检查连接状态
            if (_protocol == InstrumentProtocol.TCP || _protocol == InstrumentProtocol.RawSocket)
            {
                if (_tcpClient?.Client == null || !_tcpClient.Connected)
                {
                    await ReconnectAsync(cancellationToken).ConfigureAwait(false);
                }
            }
        }

        /// <summary>
        /// 重连
        /// </summary>
        private async Task ReconnectAsync(CancellationToken cancellationToken)
        {
            for (int retry = 0; retry < _maxRetryCount; retry++)
            {
                try
                {
                    await DisconnectAsync().ConfigureAwait(false);
                    await Task.Delay(_reconnectInterval, cancellationToken).ConfigureAwait(false);
                    await InternalConnectAsync(cancellationToken).ConfigureAwait(false);
                    
                    lock (_connectionLock)
                    {
                        _isConnected = true;
                        _connectionEvent.Set();
                    }
                    
                    OnConnectionStatusChanged($"仪器 {InstrumentId} 重连成功");
                    return;
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                    if (retry == _maxRetryCount - 1)
                        throw;
                }
            }
        }
        #endregion

        #region 命令发送
        /// <summary>
        /// 发送命令(异步)
        /// </summary>
        public async Task<InstrumentResponse> SendCommandAsync(
            string command, 
            TimeSpan? timeout = null,
            CancellationToken cancellationToken = default)
        {
            if (_isDisposed)
                throw new ObjectDisposedException(nameof(NetworkInstrumentController));

            var cmd = new InstrumentCommand(command, timeout ?? _defaultTimeout, cancellationToken);
            _commandQueue.Enqueue(cmd);
            _queueSemaphore.Release();

            return await cmd.CompletionSource.Task.ConfigureAwait(false);
        }

        /// <summary>
        /// 发送二进制命令
        /// </summary>
        public async Task<InstrumentResponse> SendBinaryCommandAsync(
            byte[] commandBytes,
            TimeSpan? timeout = null,
            CancellationToken cancellationToken = default)
        {
            if (_isDisposed)
                throw new ObjectDisposedException(nameof(NetworkInstrumentController));

            var cmd = new InstrumentCommand(commandBytes, timeout ?? _defaultTimeout, cancellationToken);
            _commandQueue.Enqueue(cmd);
            _queueSemaphore.Release();

            return await cmd.CompletionSource.Task.ConfigureAwait(false);
        }

        /// <summary>
        /// 批量发送命令
        /// </summary>
        public async Task<List<InstrumentResponse>> SendCommandsAsync(
            IEnumerable<string> commands,
            TimeSpan? timeout = null,
            CancellationToken cancellationToken = default)
        {
            var tasks = commands.Select(cmd => 
                SendCommandAsync(cmd, timeout, cancellationToken)).ToList();
            return await Task.WhenAll(tasks).ConfigureAwait(false);
        }
        #endregion

        #region 命令队列处理
        /// <summary>
        /// 处理命令队列
        /// </summary>
        private async Task ProcessCommandQueueAsync()
        {
            while (!_globalCancellationTokenSource.Token.IsCancellationRequested)
            {
                try
                {
                    await _queueSemaphore.WaitAsync(_globalCancellationTokenSource.Token).ConfigureAwait(false);

                    if (_commandQueue.TryDequeue(out var command))
                    {
                        await ProcessSingleCommandAsync(command).ConfigureAwait(false);
                    }
                }
                catch (OperationCanceledException)
                {
                    // 正常退出
                    break;
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                }
            }
        }

        /// <summary>
        /// 处理单个命令
        /// </summary>
        private async Task ProcessSingleCommandAsync(InstrumentCommand command)
        {
            if (command.CancellationToken.IsCancellationRequested)
            {
                command.CompletionSource.TrySetCanceled();
                return;
            }

            var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(
                command.CancellationToken,
                _globalCancellationTokenSource.Token);

            using (linkedCts)
            {
                try
                {
                    // 设置超时
                    using var timeoutCts = new CancellationTokenSource(command.Timeout);
                    using var combinedCts = CancellationTokenSource.CreateLinkedTokenSource(
                        linkedCts.Token, timeoutCts.Token);

                    // 确保连接
                    await EnsureConnectedAsync(combinedCts.Token).ConfigureAwait(false);

                    // 发送命令
                    var response = await SendAndReceiveAsync(command, combinedCts.Token).ConfigureAwait(false);
                    
                    Interlocked.Increment(ref _totalCommandsSent);
                    _lastActivityTime = DateTime.UtcNow;
                    
                    command.CompletionSource.TrySetResult(response);
                    OnCommandCompleted(response);
                }
                catch (OperationCanceledException ex)
                {
                    if (command.CancellationToken.IsCancellationRequested)
                        command.CompletionSource.TrySetCanceled();
                    else if (ex.CancellationToken == _globalCancellationTokenSource.Token)
                        command.CompletionSource.TrySetCanceled();
                    else
                    {
                        Interlocked.Increment(ref _failedCommands);
                        command.CompletionSource.TrySetException(
                            new InstrumentControlException("命令执行超时", ex));
                    }
                }
                catch (Exception ex)
                {
                    Interlocked.Increment(ref _failedCommands);
                    command.CompletionSource.TrySetException(
                        new InstrumentControlException("命令执行失败", ex));
                    OnErrorOccurred(ex);
                }
            }
        }

        /// <summary>
        /// 发送并接收数据
        /// </summary>
        private async Task<InstrumentResponse> SendAndReceiveAsync(
            InstrumentCommand command, 
            CancellationToken cancellationToken)
        {
            var startTime = DateTime.UtcNow;
            
            try
            {
                byte[] responseData = null;

                lock (_sendLock) // 确保同一时间只有一个线程在发送
                {
                    switch (_protocol)
                    {
                        case InstrumentProtocol.TCP:
                        case InstrumentProtocol.RawSocket:
                            // 发送命令
                            _networkStream.Write(command.CommandBytes, 0, command.CommandBytes.Length);
                            
                            // 接收响应
                            responseData = ReceiveDataFromStream(_networkStream, cancellationToken);
                            break;

                        case InstrumentProtocol.UDP:
                            // UDP 发送
                            var sentBytes = await _udpClient.SendAsync(
                                command.CommandBytes, command.CommandBytes.Length).ConfigureAwait(false);
                            
                            // UDP 接收
                            var udpResult = await _udpClient.ReceiveAsync()
                                .WithCancellation(cancellationToken).ConfigureAwait(false);
                            responseData = udpResult.Buffer;
                            break;
                    }
                }

                var endTime = DateTime.UtcNow;
                var responseTime = endTime - startTime;

                return new InstrumentResponse
                {
                    IsSuccess = true,
                    RawData = responseData,
                    Message = "命令执行成功",
                    ResponseTime = responseTime,
                    Timestamp = endTime
                };
            }
            catch (Exception ex)
            {
                // 标记连接可能已断开
                lock (_connectionLock)
                {
                    _isConnected = false;
                    _connectionEvent.Reset();
                }
                throw;
            }
        }

        /// <summary>
        /// 从流接收数据
        /// </summary>
        private byte[] ReceiveDataFromStream(NetworkStream stream, CancellationToken cancellationToken)
        {
            using var memoryStream = new MemoryStream();
            var buffer = new byte[_receiveBufferSize];
            int bytesRead;

            do
            {
                cancellationToken.ThrowIfCancellationRequested();
                bytesRead = stream.Read(buffer, 0, buffer.Length);
                memoryStream.Write(buffer, 0, bytesRead);
                
                // 检查是否还有数据可读(非阻塞检查)
                if (!stream.DataAvailable)
                    break;

            } while (bytesRead > 0);

            return memoryStream.ToArray();
        }
        #endregion

        #region 事件触发方法
        protected virtual void OnCommandCompleted(InstrumentResponse response)
        {
            CommandCompleted?.Invoke(this, response);
        }

        protected virtual void OnConnectionStatusChanged(string status)
        {
            ConnectionStatusChanged?.Invoke(this, status);
        }

        protected virtual void OnErrorOccurred(Exception exception)
        {
            ErrorOccurred?.Invoke(this, exception);
        }
        #endregion

        #region 监控与诊断
        /// <summary>
        /// 获取控制器状态
        /// </summary>
        public string GetStatus()
        {
            return $"""
                仪器控制器状态:
                仪器ID: {InstrumentId}
                连接状态: {(IsConnected ? "已连接" : "未连接")}
                连接地址: {ConnectionString}
                协议类型: {_protocol}
                总命令数: {TotalCommandsSent}
                失败命令: {FailedCommands}
                成功率: {SuccessRate:F2}%
                最后活动: {LastActivityTime:yyyy-MM-dd HH:mm:ss}
                队列长度: {_commandQueue.Count}
                """;
        }

        /// <summary>
        /// 清空命令队列
        /// </summary>
        public void ClearCommandQueue()
        {
            while (_commandQueue.TryDequeue(out var command))
            {
                command.CompletionSource.TrySetCanceled();
            }
        }

        /// <summary>
        /// 等待所有命令完成
        /// </summary>
        public async Task WaitForCompletionAsync(TimeSpan timeout)
        {
            var startTime = DateTime.UtcNow;
            
            while (_commandQueue.Count > 0)
            {
                if (DateTime.UtcNow - startTime > timeout)
                    throw new TimeoutException("等待命令完成超时");
                
                await Task.Delay(100).ConfigureAwait(false);
            }
        }
        #endregion

        #region 资源清理
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (_isDisposed)
                return;

            _isDisposed = true;

            if (disposing)
            {
                _globalCancellationTokenSource.Cancel();
                _globalCancellationTokenSource.Dispose();
                
                _processingTask?.Wait(TimeSpan.FromSeconds(5));
                _processingTask?.Dispose();
                
                DisconnectAsync().Wait(TimeSpan.FromSeconds(5));
                
                ClearCommandQueue();
                
                _queueSemaphore.Dispose();
                _connectionEvent.Dispose();
                
                _networkStream?.Dispose();
                _tcpClient?.Dispose();
                _udpClient?.Dispose();
            }
        }

        ~NetworkInstrumentController()
        {
            Dispose(false);
        }
        #endregion
    }

    #region 扩展方法
    public static class TaskExtensions
    {
        public static async Task<T> WithCancellation<T>(this Task<T> task, CancellationToken cancellationToken)
        {
            var tcs = new TaskCompletionSource<bool>();
            
            using (cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs))
            {
                if (task != await Task.WhenAny(task, tcs.Task).ConfigureAwait(false))
                {
                    throw new OperationCanceledException(cancellationToken);
                }
            }
            
            return await task.ConfigureAwait(false);
        }
    }

    /// <summary>
    /// 仪器控制器工厂
    /// </summary>
    public static class InstrumentControllerFactory
    {
        private static readonly ConcurrentDictionary<string, NetworkInstrumentController> _controllers = 
            new ConcurrentDictionary<string, NetworkInstrumentController>();

        public static NetworkInstrumentController GetOrCreateController(
            string instrumentId,
            string host,
            int port,
            InstrumentProtocol protocol = InstrumentProtocol.TCP)
        {
            return _controllers.GetOrAdd(instrumentId, id =>
                new NetworkInstrumentController(id, host, port, protocol));
        }

        public static bool TryGetController(string instrumentId, out NetworkInstrumentController controller)
        {
            return _controllers.TryGetValue(instrumentId, out controller);
        }

        public static bool RemoveController(string instrumentId)
        {
            if (_controllers.TryRemove(instrumentId, out var controller))
            {
                controller.Dispose();
                return true;
            }
            return false;
        }
    }
    #endregion

    #region 使用示例
    public class InstrumentControlExample
    {
        public static async Task DemonstrateUsage()
        {
            // 1. 创建仪器控制器
            var controller = new NetworkInstrumentController(
                instrumentId: "Oscilloscope_001",
                host: "192.168.1.100",
                port: 5025,
                protocol: InstrumentProtocol.TCP,
                defaultTimeout: TimeSpan.FromSeconds(10));

            // 订阅事件
            controller.ConnectionStatusChanged += (sender, status) => 
                Console.WriteLine($"连接状态: {status}");
            controller.CommandCompleted += (sender, response) => 
                Console.WriteLine($"命令完成: {response.Message}, 耗时: {response.ResponseTime.TotalMilliseconds}ms");
            controller.ErrorOccurred += (sender, ex) => 
                Console.WriteLine($"错误: {ex.Message}");

            try
            {
                // 2. 连接到仪器
                await controller.ConnectAsync();

                // 3. 发送命令
                var response = await controller.SendCommandAsync("*IDN?\n");
                if (response.IsSuccess)
                {
                    Console.WriteLine($"仪器标识: {response.GetString()}");
                }

                // 4. 批量发送命令
                var commands = new[]
                {
                    "CONF:VOLT:DC 10,0.001\n",
                    "READ?\n",
                    "SYST:ERR?\n"
                };

                var responses = await controller.SendCommandsAsync(commands);
                foreach (var resp in responses)
                {
                    Console.WriteLine($"响应: {resp.GetString()}");
                }

                // 5. 获取状态
                Console.WriteLine(controller.GetStatus());

                // 6. 使用工厂模式创建/获取控制器
                var factoryController = InstrumentControllerFactory.GetOrCreateController(
                    "Multimeter_002", "192.168.1.101", 5025);

                await factoryController.SendCommandAsync("*RST\n");
            }
            catch (InstrumentControlException ex)
            {
                Console.WriteLine($"仪器控制异常: {ex.Message}");
            }
            finally
            {
                // 7. 清理资源
                await controller.DisconnectAsync();
                controller.Dispose();
            }
        }
    }
    #endregion
}

设计要点说明:

1. 线程安全实现

  • 双重锁机制:连接状态管理使用双重检查锁
  • 并发队列:使用 ConcurrentQueue 存储命令
  • 信号量控制:使用 SemaphoreSlim 控制队列处理
  • 互斥发送:使用锁确保同一时间只有一个线程发送数据

2. 连接管理

  • 自动重连机制(可配置重试次数和间隔)
  • 连接状态监控和事件通知
  • 支持TCP、UDP和原始Socket协议

3. 错误处理

  • 自定义异常类型 InstrumentControlException
  • 完善的异常捕获和事件通知
  • 超时控制和取消支持

4. 异步设计

  • 完全基于async/await的异步编程
  • 支持CancellationToken取消操作
  • 非阻塞的命令队列处理

5. 监控和诊断

  • 统计信息(成功率、响应时间等)
  • 状态查询方法
  • 事件系统用于监控

6. 资源管理

  • 实现IDisposable模式
  • 正确的资源清理和释放
  • 使用工厂模式管理多个控制器实例

7. 扩展性

  • 支持多种协议
  • 可配置的超时和缓冲区大小
  • 支持二进制命令和文本命令

使用建议:

  1. 单例模式:对于每个仪器,使用工厂模式确保只有一个控制器实例
  2. 异常处理:始终处理 InstrumentControlException
  3. 资源清理:使用using语句或在适当的时候调用Dispose
  4. 监控:订阅事件以便监控仪器状态
  5. 超时设置:根据仪器响应时间合理设置超时

这个实现提供了生产级的线程安全仪器控制功能,适用于各种测试测量和自动化控制场景。