我目前正在开发一个项目,我使用带有UWP应用程序的串口。 有时我遇到的问题是我需要一定数量的数据,但是当我没有获得那么多的数据时,我的串口会一直读取,直到我手动取消它。
当我初始化serialDevice时,我设置了serialDevice.ReadTimeout参数但是没有做任何事情。 我还试图将cancellationToken绑定到ReadTimeout参数,但这也不起作用。如果我没记错的话,在它完成之前取消了我的方法...
有没有办法实现工作超时?
我用它作为我的基础:
public class ReadWriteAdapter
{
public SemaphoreSlim Semaphore { get; }
private static readonly object LockObject = new object();
private static ReadWriteAdapter _instance;
public static ReadWriteAdapter Current
{
get
{
if (_instance == null)
{
lock (LockObject)
{
if (_instance == null)
{
_instance = new ReadWriteAdapter();
}
}
}
return _instance;
}
}
private ReadWriteAdapter()
{
Semaphore = new SemaphoreSlim(1, 1);
}
private SerialDevice _serialPort;
public CancellationTokenSource ReadCancellationTokenSource;
public CancellationTokenSource WriteCancellationTokenSource;
private object _readCancelLock = new object();
private object _writeCancelLock = new object();
private DataWriter _dataWriter;
private DataReader _dataReader;
public bool IsDeviceInitialized()
{
return _serialPort != null;
}
public async Task<string> Init()
{
try
{
if (_serialPort != null) return "port already configured!";
var aqs = SerialDevice.GetDeviceSelector("COM3");
var devices = await DeviceInformation.FindAllAsync(aqs, null);
if (!devices.Any()) return "no devices found!";
await OpenPort(devices[0].Id);
WriteCancellationTokenSource = new CancellationTokenSource();
ReadCancellationTokenSource = new CancellationTokenSource();
return "found port!";
}
catch (Exception ex)
{
return ex.Message;
}
}
private async Task OpenPort(string deviceId)
{
try
{
_serialPort = await SerialDevice.FromIdAsync(deviceId);
if (_serialPort != null)
{
_serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
_serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
_serialPort.BaudRate = 19200;
_serialPort.Parity = SerialParity.None;
_serialPort.StopBits = SerialStopBitCount.One;
_serialPort.DataBits = 8;
_serialPort.Handshake = SerialHandshake.None;
_dataWriter = new DataWriter(_serialPort.OutputStream);
_dataReader = new DataReader(_serialPort.InputStream);
}
}
catch (Exception ex)
{
throw ex;
}
}
private async Task<byte[]> ReadAsync(CancellationToken cancellationToken, uint readBufferLength)
{
Task<uint> loadAsyncTask;
var returnArray = new byte[readBufferLength];
lock (_readCancelLock)
{
cancellationToken.ThrowIfCancellationRequested();
_dataReader.InputStreamOptions = InputStreamOptions.Partial;
loadAsyncTask = _dataReader.LoadAsync(readBufferLength).AsTask(cancellationToken);
}
var bytesRead = await loadAsyncTask;
if (bytesRead > 0)
{
_dataReader.ReadBytes(returnArray);
}
return returnArray;
}
public async Task<uint> WriteCommand(string PairedCommand)
{
var commandArray = StringToByteArray(PairedCommand);
uint taskResult = 0;
try
{
if (_serialPort != null)
{
if (_dataWriter == null)
{
_dataWriter = new DataWriter(_serialPort.OutputStream);
taskResult = await WriteAsync(WriteCancellationTokenSource.Token, commandArray);
}
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
_dataWriter.DetachStream();
_dataWriter.Dispose();
_dataWriter = null;
}
return taskResult;
}
public async Task<uint> WriteAsync(CancellationToken cancellationToken, byte[] data)
{
Task<uint> storeAsyncTask;
try
{
lock (_writeCancelLock)
{
cancellationToken.ThrowIfCancellationRequested();
_dataWriter.WriteBytes(data);
storeAsyncTask = _dataWriter.StoreAsync().AsTask(cancellationToken);
}
}
catch (Exception ex)
{
throw ex;
}
return await storeAsyncTask;
}
public async Task<byte[]> Listen(uint bufferLength)
{
var listen = new byte[bufferLength];
try
{
if (_serialPort != null)
{
if (_dataReader == null)
{
_dataReader = new DataReader(_serialPort.InputStream);
}
listen = await ReadAsync(ReadCancellationTokenSource.Token, bufferLength);
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (_dataReader != null)
{
_dataReader.DetachStream();
_dataReader.Dispose();
_dataReader = null;
}
}
return listen;
}
public byte[] StringToByteArray(string str)
{
var enc = new ASCIIEncoding();
return enc.GetBytes(str);
}
public void CancelReadTask()
{
lock (_readCancelLock)
{
if (ReadCancellationTokenSource == null) return;
if (ReadCancellationTokenSource.IsCancellationRequested) return;
ReadCancellationTokenSource.Cancel();
ReadCancellationTokenSource = new CancellationTokenSource();
}
}
private void CancelWriteTask()
{
lock (_writeCancelLock)
{
if (WriteCancellationTokenSource == null) return;
if (WriteCancellationTokenSource.IsCancellationRequested) return;
WriteCancellationTokenSource.Cancel();
WriteCancellationTokenSource = new CancellationTokenSource();
}
}
}
我用类似的代码(简短版)调用它:
public class ReadData
{
private ReadBlock readBlock = new ReadBlock();
public async Task<byte[]> ReadParaBlock()
{
await ReadWriteAdapter.Current.Semaphore.WaitAsync();
await ReadWriteAdapter.Current.WriteCommand("getData");
byte[] recievedArray = await ReadWriteAdapter.Current.Listen(100);
ReadWriteAdapter.Current.Semaphore.Release();
return recievedArray;
}
}