troubleshooting Question

Multi threading issue?

Avatar of websss
websssFlag for Kenya asked on
.NET ProgrammingC#
2 Comments1 Solution133 ViewsLast Modified:
I am working on a gps tracking  Windows application that uses Asychronous socket communication to talk to the tracking  device(s).

I'm having a problem where data from one unit is contaminating data with another unit
The IMEI in the unique identifier
However the IMEI only comes in on the handshake, after this, the IMEI isn't sent, so i store the IMEI and REMOTE ENDPOINT in an object, and use the REMOTE ENDPOINT (which is available on each subsequent message) to look up the IMEI number

The issue seems to be related to the app being multi threaded.
Here is the process:

So I basically create a listener socket:

tcp_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Bind to an endpoint
tcp_listener.Bind(new IPEndPoint(IPAddress.Parse(“”), 10005));

Set up a callback to be notified of connection requests:

tcp_listener.BeginAccept(new AsyncCallback(OnConnectRequest), tcp_listener);

so upto this point, we are ready to accept connection requests from devices. When a device tries to connect, OnConnectRequest() event handler is fired
Socket client;

public void OnConnectRequest( IAsyncResult ar )
                Socket listener = (Socket)ar.AsyncState;
                listener.BeginAccept(new AsyncCallback(OnConnectRequest), listener);
            catch (SocketException e)

To receive data asynchronously, it is necessary to setup an AsyncCallback to handle events triggered by the Socket such as new data and loss of connection. This is done using the following method

private byte []    m_byBuff = new byte[1024];    // Received data buffer

public void SetupReceiveCallback( Socket sock )
        AsyncCallback recieveData = new AsyncCallback( OnReceivedData );
        sock.BeginReceive( m_byBuff, 0, m_byBuff.Length, 
                           SocketFlags.None, recieveData, sock );
    catch( Exception ex )
        MessageBox.Show( this, ex.Message, "Setup Recieve Callback failed!" );

The SetupReceiveCallback method starts a BeginReceive using a delegate pointing to the OnReceiveData() method that follows. It also passes a buffer for the receive data to be inserted into.

Now herein lies the problem. The device connects and sends a login message which has the device ID (IMEI), this happens only once during the life of the socket. I normally create a field on a custom socket object and store the device ID. Any subsequent data that comes in on this particular Socket object gets tied to the initial device ID.

Each device that connects has it’s own socket object created and this stores the information about the connection including the device ID.

I have a separate class that processes the data unto which we pass the Device ID of the connected object. So when data comes in on OnReceiveData(), I just pass that data to the particular socket object that was created when the particular device connected.

However, I have had issues where the Device ID of a particular connected device get’s passed to a totally different Socket object. As a result, data from device A gets assigned to device B despite each having a separate Socket object ties to their particular connections. Here’s the sequence of events:

  • Device connects to app:
  • App creates a socket object for the particular device
  • Device starts sending data
  • Data is handled by OnRecievedData() delegate
  • Device sends first data (login data) which is the IMEI of the device
  • The IMEI data is assigned to the socket object

if (protocol_check[3] == "01")
                    string[] arr_data = new string[aryRet.Length];
                    for (int i = 0; i < aryRet.Length; i++)
                        arr_data[i] = int.Parse(aryRet[i].ToString()).ToString("X").PadLeft(2, '0');
                    StringBuilder sb = new StringBuilder();
                    sb.Append(arr_data[0] + arr_data[1] + "05");
                    if (protocol_check[2]=="11")
                        sb.Append(arr_data[16] + arr_data[17]);
                        sb.Append(arr_data[12] + arr_data[13]);

                    byte[] dataPacket = hexStringToByteArray(sb.ToString());
                    var crc16 = GetCrc16(dataPacket, 2, 4);

                    string error_check = string.Format("{0:X}", (int)crc16);
                    sb.Append(error_check + "0D0A"                     //get the IMEI
                    for (int i = 4; i < 12; i++)
                        nUnitID += arr_data[i];
                    nUnitID = nUnitID.Substring(1, 15);

                    //assign to active socket
             client.DEVICE_ID = nUnitID;

Device sends location data, this is assigned to the Connected Sockets’ device ID.
Instantiate an instance of the class that handles the data:
cdataHandler cdh = new cDataHandler();
Pass it the data received and IMEI of the device:
cdh.processMsg(Message, IMEI);

The IMEI that is passed to cdh.processMsg is fine and corresponds to the sending device. However when you examine the IMEI inside cdh.processMsg, it’s totally different from what was passed in through on OnRecievedData().

Question is, why would the data on the calling Async method be different from the one on the method on the instance of the data handling class? Is this a threading issue. Despite creating function to create thread safety for the method calls on the received data, the issue still persists. What would be the best way to handle received data in such an instance so it doesn’t cross contaminate?
Join our community to see this answer!
Unlock 1 Answer and 2 Comments.
Start Free Trial
Learn from the best

Network and collaborate with thousands of CTOs, CISOs, and IT Pros rooting for you and your success.

Andrew Hancock - VMware vExpert
See if this solution works for you by signing up for a 7 day free trial.
Unlock 1 Answer and 2 Comments.
Try for 7 days

”The time we save is the biggest benefit of E-E to our team. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange.

-Mike Kapnisakis, Warner Bros