Developing a newer WPF .NET 6 application - some findings and questions #361
Unanswered
perkjelsvik
asked this question in
Q&A
Replies: 1 comment
-
Thanks for your really detailed investigation and findings. I'll need to go through in detail and run some tests on the WinRTNetworkStream and related functionality. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
For a new WPF application I'm developing, I wanted to use .NET 6 and the newer WinRT implementation of the library. Therefore I've targeted
net6.0-windows10.0.22000
. I also wanted to do it in a asynchronous manner this time around. Connecting and disconnecting etc. to the device I'm using is no problem, but I've encountered some issues when it comes to writing and reading to the device. The device has an older Bluetooth 2.1 chip. It's quite simple communication back-and-forth using RFCOMM. Typical usecase can be that the PC sends a command, saystatus?
and the device will answer something likestatus=idle\r
.In the application we want to connect to our device, and keep the connection alive throughout the lifetime of the application. Most of the time it might be idle, but every now and then we need to send messages back and forth. And sometimes the device will enter a mode where it continuously streams data to the computer, a message every 25 ms or so.
Previous experience with legacy library
I've used the legacy library for WPF applications on .NET Framework earlier. There we typically handled communication in this manner:
This is a simplified pseudocode version with elements omitted, but it captures the essence of the communication. In the older application this seems to work well.
Writing to NetworkStream
I found that if I use the memory-based overload (which CA1835 recommends) to write, the data is not acutally sent, even though I flush the data. Not sure why this happens. Both of the cases below does not work.
In any case, this seems to work consistently:
When I say the memory-based overloads doesn't work I mean that the device does not receive the command, but it clearly does so in the last case.
Reading from NetworkStream
Checking if data is available
When it comes to reading I'm facing a couple of issues. First of all, in the
WinRTNetworkStream
, I see that bothDataAvailable
andLength
has an implementation. However,CanSeek
is set to false, and if I try to access either property, I get the following exception:So they can't be used to determine if there's data available.
Reading async from NetworkStream using CancellationToken
I've tried the following:
Now, if there is no data the task will cancel, and we move on. I can still write to the NetworkStream, but as soon as I flush the data, I will get a
ObjectDisposedException
exception. Perhaps this is the expected behavior, but that means I need to reestablish the connection completely, as it seems the underlying stream (or socket) is no longer available. (?)I can get around this by doing the following:
But the problem here, as I see it, is that if I move on, the
readTask
will just wait forever, until data eventually comes in, or it is garbage collected. Say I start a new read operation, then the first data arriving from the device will most likely pop into this task before the newreadTask
. I've found workarounds (see below), but I suspect this is a relatively normal usecase, so I'm left wondering if I'm missing something in how to handle this?Workarounds
In a normal usecase the above is not much of an issue. Usually I will send a message and expect a reply. If I don't receive a reply within a certain amount of time then there is something wrong with the communication, and that should be handled accordingly. Most likely we need to close connections, notify the user about the error, and then initiate a new connection again if the user wants to.
However, there's usecases where the device will enter a state where it continuously sends data to the computer. It might be in this state when we first connect to it. When it's sending data it won't stop until it receives a stop command, and then the underlying buffer will still receive data for a little while. Therefore it's useful with a method that sends stop, and then empties all incoming data from the underlying buffer so that it is back in idle state (no data transfer). In this case we won't send a command that receives a reply - we simply want to read until we no longer can read. But if I do that, then I will eventually get a
readTask
that never returns, and now we're stuck.I have found a workaround to this issue which essentially uses the logic from above, but whenever the
readTask
times out (i.e. the device has stopped streaming data to the computer every 25 ms) I send a new command that the device should always reply to. ThereadTask
is then able to return and we can exit the method knowing that we're back in an idle state. This works, but I suspect there's better solutions to handle it?Pseudocode to illustrate:
In this case it will immediately get the result if the
readTask
finished first, and in the case it times out it will get the expected reply after we write a command that should always produce a reply.Questions
So, to summarize, I'm wondering about the following:
WinRTNetworkStream
be updated to supportDataAvailable
, and/or is there plans to further build out its features?Beta Was this translation helpful? Give feedback.
All reactions