SDS2000X示波器设备调试
This commit is contained in:
@@ -230,7 +230,89 @@ namespace DeviceCommand.Base
|
||||
_commLock.Release();
|
||||
}
|
||||
}
|
||||
#region 扩展:读取所有可用的二进制网络字节 (无 SCPI 块头解析)
|
||||
|
||||
/// <summary>
|
||||
/// 无锁核心方法:发送命令并一次性读取所有回传的二进制原始数据包(不进行 # 协议头解析,专用于读取纯文件流如 PNG)
|
||||
/// </summary>
|
||||
private async Task<byte[]> LoglessReadAllBytesAsync(string queryCommand, CancellationToken ct)
|
||||
{
|
||||
if (!IsConnected) throw new InvalidOperationException("TCP未连接。");
|
||||
|
||||
// 1. 发送查询命令(例如 :PRINt? PNG\n)
|
||||
await LoglessSendAsync(Encoding.UTF8.GetBytes(queryCommand), ct);
|
||||
|
||||
NetworkStream stream = _tcpClient.GetStream();
|
||||
|
||||
// 2. 鼎阳示波器的截图数据大概在 100KB - 800KB 左右,使用动态内存流接收整个包
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
byte[] buffer = new byte[8192]; // 8KB 缓冲区
|
||||
|
||||
try
|
||||
{
|
||||
// 先给设备短暂的反应时间,等待数据到达网络缓冲区
|
||||
int delayCount = 0;
|
||||
while (!_tcpClient.GetStream().DataAvailable && delayCount < 50)
|
||||
{
|
||||
await Task.Delay(10, ct);
|
||||
delayCount++;
|
||||
}
|
||||
|
||||
// 循环读取,直到网络流中没有更多数据
|
||||
do
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
int read = ReceiveTimeout > 0
|
||||
? await stream.ReadAsync(buffer, 0, buffer.Length, ct)
|
||||
.WaitAsync(TimeSpan.FromMilliseconds(ReceiveTimeout), ct)
|
||||
.ConfigureAwait(false)
|
||||
: await stream.ReadAsync(buffer, 0, buffer.Length, ct).ConfigureAwait(false);
|
||||
|
||||
if (read == 0) break; // 远程流关闭
|
||||
|
||||
ms.Write(buffer, 0, read);
|
||||
|
||||
// 如果流里没有剩余数据了,退出读取(防止 ReadAsync 在没有数据时无限阻塞等待)
|
||||
if (!stream.DataAvailable)
|
||||
{
|
||||
// 极短延时再确认一次,防止分包网络延迟引起的“假结束”
|
||||
await Task.Delay(30, ct);
|
||||
if (!stream.DataAvailable)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
catch (TimeoutException ex)
|
||||
{
|
||||
await ResetConnectionAsync(ct);
|
||||
throw new TimeoutException($"读取二进制大包超时(等待:{ReceiveTimeout} ms),链路已重置。", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 【公开方法】发送命令并读取设备回传的全部原始二进制字节数组(不带协议头解析,直接返回整个字节缓冲区)
|
||||
/// </summary>
|
||||
public async Task<byte[]> ReadAllBytesAsync(string queryCommand, CancellationToken ct = default)
|
||||
{
|
||||
await _commLock.WaitAsync(ct);
|
||||
try
|
||||
{
|
||||
return await LoglessReadAllBytesAsync(queryCommand, ct);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_commLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
public void Dispose()
|
||||
{
|
||||
_tcpClient?.Dispose();
|
||||
|
||||
Reference in New Issue
Block a user