数据读取器.即使数据可用,LoadAsync也会无限等待
本文关键字:数据 LoadAsync 等待 无限 读取 | 更新日期: 2023-09-27 18:18:24
我有以下代码在我的Windows phone 8应用程序。
//connection code, done during app start
socket = new StreamSocket();
await socket.ConnectAsync(serverHostName, serviceName);
dataReader = new DataReader(socket.InputStream);
dataReader.InputStreamOptions = InputStreamOptions.Partial;
dataWriter = new DataWriter(socket.OutputStream);
连接建立后,我有另一个线程检查传入的网络数据包
await dataReader.LoadAsync(2048);
dataReader.ReadBytes(buffer);
----------
工作流程如下
- 电话使用套接字连接到服务器。ConnectAsync
- 服务器响应初始消息(电话在dataReader中正确接收此消息)。LoadAsync函数)
- 手机现在发送'业务特定'请求
- 服务器现在回复'业务特定'响应(问题在于这里。
"工作状态"answers"非工作状态"之间没有场景差异。
所以我试着调试这个。I 为dataReader设置了一个断点。LoadAsync并看到执行在调用时无限等待。
为了确保服务器正确发送数据,我在Windows phone模拟器中运行应用程序,并在PC中运行WireShark网络分析器。我可以看到正在接收电话IP地址的数据包。
有没有人知道为什么dataReader。LoadAsync函数调用根本不返回,当有数据准备在套接字中读取?
我也面临同样的问题。这对于蓝牙RFCOMM SPP串行端口设备来说尤其糟糕,因为底层RFCOMM -object不提供设置ReadTimeout值的功能。编辑:InputStreamOptions。部分选项似乎在UWP Win10平台上工作,但只有当您已经知道您期望的大量数据时,它才有用。否则,它将无限期地等待最后一次调用。
我几乎放弃了,当我在这些行下面的参考文献中发现通过使用CancellationTokenSource
来解决问题时//connect your Windows.Devices.Bluetooth.Rfcomm.RfcommDeviceService
// see the Bluetooth chat example
[...]
StreamSocket streamSocket = new StreamSocket();
await streamSocket.ConnectAsync(...); //connect to Bluetooth device
DataReader dataReader = new DataReader(inputStream); // to read from the stream
try
{
var timeoutSource = new CancellationTokenSource(1000); // 1000 ms
uint numberBytesToRead = 256;
var data = await dataReader.LoadAsync(numberBytesToRead).AsTask(timeoutSource.Token);
}
catch (TaskCanceledException)
{
// we will get here, and everything looks fine, but the problem is:
// The underlying streamSocket is also closed!
// we can not re-use the streamSocket. Any more calls to LoadAsync results in exceptions (something about the object being not assigned...)
// we need to do a full await streamSocket.ConnectAsync(...) again, but that takes ~3 seconds.
}
所以这个方法只是在超时时的最后一招。
@mayu的方法工作得很好(serialDevice.ReadTimeout),但仅适用于Windows.Devices.SerialCommunication类的设备。串行设备,但不在上Windows.Devices.Bluetooth.Rfcomm.RfcommDeviceService。我不知道TCP/IP套接字的情况。
简而言之,RFCOMM SPP蓝牙连接是否有可用的超时?或者任何方法提前知道如果。loadasync(1)将阻塞,因为没有新的数据可用?
这个在MSDN上的家伙有完全相同的问题,但是微软也不知道答案:https://social.msdn.microsoft.com/Forums/vstudio/en-US/71ea17d4-ca16-43c2-ab43-02d5301def3f/chow-to-set-timeout-on-streamsocketreadasync?forum=wpdevelop
引用:
在UWP StreamSocket中,我可以超时读取数据并在超时后保持连接打开
https://social.msdn.microsoft.com/Forums/en-US/8a5c4fdc-28d6-4a22-8df6-bc519efeaa4d/how-to-control-the-timeout-for-reading-from-streamsocket?forum=winappswithcsharpSocketStream的数据读取器
"根据使用InputStreamOptions时的文档。部分,您应该使用UnconsummedBufferLength而不是硬编码值"
那个样品好像坏了。
"await reader.LoadAsync(reader.UnconsumedBufferLength);"相当于
等待reader.LoadAsync (0);然后不可能读取任何数据,因为没有缓冲区可以读取。
我现在正在测试这个,它看起来像"reader"。InputStreamOptions = Partial;"没有任何效果。我唯一的解决方法是降低读取超时
根据文档使用InputStreamOptions。部分,您应该使用UnconsummedBufferLength而不是硬编码的值:
DataReader reader = new DataReader(clientSocket.InputStream);
// Set inputstream options so that we don't have to know the data size
reader.InputStreamOptions = Partial;
await reader.LoadAsync(reader.UnconsumedBufferLength);
我有一个类似的问题使用Windows远程Arduino库和SerialUSB流。我不得不改变这个库并调用LoadAsync(1)而不是原来的LoadAsync(100)。现在代码运行正常了。
见:https://github.com/ms-iot/remote-wiring/issues/111
对于串行设备,您需要设置
device.ReadTimeout = TimeSpan.FromMilliseconds(100);
让LoadAsync在buffer满之前返回
我发现在读取之前不知道数据大小的唯一方法是每次读取一个字节,直到我得到超时。感觉很可怕,但很有效。有没有更好的办法?
private async Task ReadData(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
DataReaderObject.InputStreamOptions = InputStreamOptions.Partial;
uint data = 0;
uint bufferLength = DataReaderObject.UnconsumedBufferLength;
var timeoutSource = new CancellationTokenSource(100); // 100 ms
try
{
while (true)
{
data = await DataReaderObject.LoadAsync(1).AsTask(timeoutSource.Token);
if (data > 0)
{
String temp = DataReaderObject.ReadString(data);
TemperatureValue.Text += temp.Trim();
}
}
}
catch (Exception)
{
;
}
}