PORTS Forum
Ports and Interfaces => USB => Topic started by: Dominik on November 29, 2011, 10:32:31 am
-
Hi,
I'm searching for a short C# example how to add an Thread which runs a loop to read out input reports and add the received data to a textbox (if there is any data). I have problems to stop running the thread loop. I don't want to use thread.abort() but setting and reading a bool variable in the loop didn't worked. I think it is because updating the WindowForm takes to much time. So I am looking for a good/fast thread example.
-
My generic HID examples use BeginInvoke to read a report in the background with a callback that displays the retrieved data on a form. So waiting for reports doesn't hang the main application. To retrieve reports continuously, the application could request a new report immediately after receiving one, and the application can stop reading whenever it wants.
http://www.lvr.com/hidpage.htm#MyExampleCode
Jan
-
Hi Jan,
thank you for your reply. I am using your C# hid example and modified it to start a reading thread:
while (boRunWorker)
{
if ((fileStreamDeviceData.Read(inputReportBuffer, 0, inputReportBuffer.Length) > 0))
{
objArray[1] = inputReportBuffer; // set received data
BeginInvoke(updel, objArray);
}
Thread.Sleep(20); // switch between threads
}
Now I think it is working, I have changed the MainForm updating routine from a MethodInvoker call to an BeginInvoke delegate routine. Or would it be better to start reading only when the thread has received some data from the device and not calling Read in loops (using asynchronousread -> Beginread?)?
But I have also another problem to send multiple bytes to my device (STM32 Microcontroller). To prepare my device I'll have to send multiple small packages of 4 bytes. I have modified the send routine not to wait for an input report. Sending one after another package stopps after sending some reports (4 bytes) calling fileStreamDeviceData.Write(outputReportBuffer, 0, outputReportBuffer.Length); for the next package. Setting some breakpoints before sending a new report prevents the windows program from getting stuck. So i have added some Thread.Sleep(); calls but it doesn't work at all. I guess that the previous send process is not completed, but how could I check if this is the problem and how could I solve that.
Thank you
Dominik!
-
I'm not sure offhand of the answer to your first question.
As for the Writes, are you waiting for Write to return before doing another? Is the device ACKing everying it receives?
Jan
-
Hi,
i have added a bool variable to check if there is a pending write process. But I also thought, that calling fileStreamDeviceData.Write(outputReportBuffer, 0, outputReportBuffer.Length); will return after sending data was completed. I have added a call of fileStreamDeviceData.flush() and it is better (but i still have to call thread.sleep). Ok i could live with that call. I'll have to check if my device is ACKing every packet. One last question: Do I have to open two device handles and two filestreams (one read, one write direction) to perform mostly "independent" read and write actions of the USB or isn't it possible to write a report to the device while a thread is waiting for data from an input report? If this isn't possible it might be a problem in my code, because I want to send some additional reports after starting the thread to check if input reports have been received.
Dominik
-
The same handle can do reads and writes.
This might be helpful:
http://stackoverflow.com/questions/4966688/c-sharp-filestream-not-blocking-untill-write-read-operation-complete
Jan
-
So i have changed my Thread loop from calling filestream.Begin(...) to filestream.BeginRead(...). To abort the thread my loop has to receive at least one report from my device to finally call EndRead(). This has to be done because calling BeginRead(...) is blocking the filestream and I couldn't find another function to abort it. To be able to send a request while waiting for data from my device I split up the original filestream in two (one reading, one writing) with two hidhandles(also reading and writing direction)!
while (boRunWorker)
{
if (boStopp)
{
outputReportBuffer[0] = 0x01; // fill the output report
outputReportBuffer[1] = 0x03;
outputReportBuffer[2] = 0x00;
outputReportBuffer[3] = 0x00;
fileStreamWrite.Write(outputReportBuffer, 0, outputReportBuffer.Length);
fileStreamWrite.Flush(true);
Thread.Sleep(0);
object obj = ar.AsyncState;
while(!ar.IsCompleted); // wait for EndRead when "calb" is executed
}
if ((botransfer == false) && (boStopp == false)) // prevent restarting BeginRead when already called and/or thread is about to stop
{
botransfer = true; // Signal pending transfer
ar = fileStreamDeviceData.BeginRead(inputReportBuffer, 0, inputReportBuffer.Length, callb, inputReportBuffer);
}
}
I think I also found a little thing in your original code: In generic_hid_cs_50.zip you added a IAsyncResult variable but didn't instantiate it in ExchangeInputAndOutputReports() when calling BeginRead: (should be something like this ar = fileStreamDeviceData.BeginRead(...); ) ?
Cheers Dominik
-
>I think I also found a little thing in your original code: In generic_hid_cs_50.zip you added a IAsyncResult variable but didn't instantiate it in ExchangeInputAndOutputReports() when calling BeginRead: (should be something like this ar = fileStreamDeviceData.BeginRead(...); ) ?
Thanks!
Jan