I’m creating an application which communicates with the device via FT2232H USB/RS232 converter. For communication I’m using FTD2XX_NET.dll library from FTDI website.
I’m using two threads:
I’ve got a problem when I’m trying to write any data to the device while the receiver’s thread is running. The main thread simply hangs up on ftdiDevice.Write function.
I tried to synchronize both threads so that only one thread can use Read/Write function at the same time, but it didn’t help.
Below code responsible for the communication. Note that following functions are methods of FtdiPort class.
Receiver’s thread
private void receiverLoop()
{
if (this.DataReceivedHandler == null)
{
throw new BackendException("dataReceived delegate is not set");
}
FTDI.FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OK;
byte[] readBytes = new byte[this.ReadBufferSize];
while (true)
{
lock (FtdiPort.threadLocker)
{
UInt32 numBytesRead = 0;
ftStatus = ftdiDevice.Read(readBytes, this.ReadBufferSize, ref numBytesRead);
if (ftStatus == FTDI.FT_STATUS.FT_OK)
{
this.DataReceivedHandler(readBytes, numBytesRead);
}
else
{
Trace.WriteLine(String.Format("Couldn't read data from ftdi: status {0}", ftStatus));
Thread.Sleep(10);
}
}
Thread.Sleep(this.RXThreadDelay);
}
}
Write function called from main thread
public void Write(byte[] data, int length) { if (this.IsOpened) { uint i = 0; lock (FtdiPort.threadLocker) { this.ftdiDevice.Write(data, length, ref i); } Thread.Sleep(1); if (i != (int)length) { throw new BackendException("Couldnt send all data"); } } else { throw new BackendException("Port is closed"); } }
Object used to synchronize two threads
static Object threadLocker = new Object();Method that starts the receiver's thread
private void startReceiver() { if (this.DataReceivedHandler == null) { return; } if (this.IsOpened == false) { throw new BackendException("Trying to start listening for raw data while disconnected"); } this.receiverThread = new Thread(this.receiverLoop); //this.receiverThread.Name = "protocolListener"; this.receiverThread.IsBackground = true; this.receiverThread.Start(); }
The ftdiDevice.Write function doesn't hang up if I comment following line:ftStatus = ftdiDevice.Read(readBytes, this.ReadBufferSize, ref numBytesRead);
A few things:
Check to see if your Read call is blocking. If so, you might not be able to call Write while the Read is blocking waiting for a response. Your API documentation may have more details on this.
Some APIs do not support multiple threads very well, even when synchronizing access. If that’s the case here, you can use a design where you delegate your Write commands to your comm thread. When I’ve used this pattern in the past, I typically queue up some sort of Command class containing the information I wish to write, and either use a threading Signal class to allow my calling ‘command’ methods to block or provide some sort of asynchronous notification.