private void Work()
        {
            try
            {
                IRequest request     = null;
                String   requestJson = string.Empty;

                _Writer = new StreamWriter(_Socket.GetStream(), Encoding.UTF8);

                //while waiting for queue to populate and thread not killed
                while (_IsRunning)
                {
                    request = _OutQueue.Dequeue();

                    if (request.IsCancelled)
                    {
                        continue;
                    }

                    request.TimeStamp = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
                    requestJson       = request.ToJsonString();

                    while (true)
                    {
                        try
                        {
                            _Writer.WriteLine(requestJson);
                            _Writer.Flush();

                            _OngoingRequests.TryAdd(request.Id, request);

                            if (GazeManager.DebugMode)
                            {
                                Debug.WriteLine("OUT: " + requestJson);
                            }

                            break;
                        }
                        catch (IOException ioe)
                        {
                            // Has writing to socket failed and may server be disconnected?
                            if (++request.RetryAttempts >= NUM_WRITE_ATTEMPTS_BEFORE_FAIL)
                            {
                                request.Finish();
                                IRequest value;
                                _OngoingRequests.TryRemove(request.Id, out value);
                                throw new Exception("OutgoingStreamHandler failed writing to stream despite several retires");
                            }

                            if (GazeManager.DebugMode)
                            {
                                Debug.WriteLine("OutgoingStreamHandler IO exception: " + ioe.Message);
                                Debug.WriteLine(ioe.StackTrace);
                            }
                        }
                    }
                }
            }
            catch (ThreadInterruptedException tie)
            {
                if (GazeManager.DebugMode)
                {
                    Debug.WriteLine("Outgoing stream handler interrupted: " + tie.Message);
                }
            }
            catch (Exception e)
            {
                Debug.WriteLine("Exception while establishing outgoing socket connection: " + e.Message);

                if (GazeManager.DebugMode)
                {
                    Debug.WriteLine(e.StackTrace);
                }
            }
            finally
            {
                try
                {
                    if (null != _Writer)
                    {
                        _Writer.Close();
                    }
                }
                catch (Exception e)
                {
                    // consume
                }

                //connection has been lost
                _NetworkLayer.Close();
            }

            if (GazeManager.DebugMode)
            {
                Debug.WriteLine("OutgoingStreamHandler closing down");
            }
        }
        private void Work()
        {
            try
            {
                _Reader = new StreamReader(_Socket.GetStream(), Encoding.UTF8);

                JsonSerializer serializer = JsonSerializer.CreateDefault();

                while (_IsRunning)
                {
                    while (!_Reader.EndOfStream /*&& IsSocketConnected()*/)
                    {
                        string responseJson = _Reader.ReadLine();

                        if (GazeManager.DebugMode)
                        {
                            Debug.WriteLine("IN: " + responseJson);
                        }

                        if (!String.IsNullOrEmpty(responseJson) && null != _ResponseListener)
                        {
                            JsonTextReader jsreader = new JsonTextReader(new StringReader(responseJson));
                            JObject        json     = (JObject)serializer.Deserialize(jsreader);
                            JToken         value;

                            int id = 0;
                            if (json.TryGetValue(Protocol.KEY_ID, out value))
                            {
                                id = (int)value;
                            }

                            //get ongoing request if any
                            IRequest request;
                            _OnGoingRequests.TryRemove(id, out request);

                            //get status code
                            json.TryGetValue(Protocol.KEY_STATUSCODE, out value);

                            ResponseBase response = null;
                            if ((int)value == (int)HttpStatusCode.OK)
                            {
                                if (request != null)
                                {
                                    //matching request handles parsing
                                    response             = (ResponseBase)request.ParseJsonResponse(json);
                                    response.TransitTime = (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - request.TimeStamp;
                                }
                                else
                                {
                                    // Incoming message has no id and is a reponse to a process or a pushed gaze data frame
                                    json.TryGetValue(Protocol.KEY_CATEGORY, out value);

                                    if (value.ToObject <String>().Equals(Protocol.CATEGORY_CALIBRATION))
                                    {
                                        // response is calibration result
                                        response = json.ToObject <CalibrationPointEndResponse>();
                                    }
                                    else if (null != (response = _NetworkLayer.ParseIncomingProcessResponse(json, value)))
                                    {
                                        // We allow the network layer extensions to optionally handle the process reponse
                                    }
                                    else
                                    {
                                        // response is gaze data frame
                                        response = json.ToObject <TrackerGetResponse>();
                                    }
                                }
                            }
                            else
                            {
                                //request failed
                                response          = json.ToObject <ResponseFailed>();
                                response.Category = "";  //we reset category to simplify parsing logic

                                if (request != null)
                                {
                                    response.TransitTime = (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - request.TimeStamp;
                                }
                            }

                            if (GazeManager.DebugMode && null != response && response.TransitTime != 0)
                            {
                                Debug.WriteLine("IN: transitTime " + response.TransitTime);
                            }

                            if (null != _ResponseListener)
                            {
                                _ResponseListener.OnGazeApiResponse(response, request);
                            }
                        }
                    }
                }
            }
            catch (ThreadInterruptedException tie)
            {
                Debug.WriteLine("Incoming stream handler interrupted: " + tie.Message);
            }
            catch (Exception e)
            {
                Debug.WriteLine("Exception while establishing incoming socket connection: " + e.Message);

                if (GazeManager.DebugMode)
                {
                    Debug.WriteLine(e.StackTrace);
                }
            }
            finally
            {
                if (null != _Reader)
                {
                    _Reader.Close();
                }

                //connection has been lost
                _NetworkLayer.Close();
            }

            if (GazeManager.DebugMode)
            {
                Debug.WriteLine("IncommingStreamHandler closing down");
            }
        }