/// <summary>
        /// Processes EmoEngine events until there is no more events or maximum processing time has elapsed
        /// </summary>
        /// <param name="maxTimeMilliseconds">maximum processing time in milliseconds</param>
        public void ProcessEvents(Int32 maxTimeMilliseconds)
        {
            Stopwatch st = new Stopwatch();

            st.Start();
            while (EdkDll.IEE_EngineGetNextEvent(hEvent) == EdkDll.EDK_OK)
            {
                if (maxTimeMilliseconds != 0)
                {
                    if (st.ElapsedMilliseconds >= maxTimeMilliseconds)
                        break;
                }
                UInt32 userId = 0;
                EdkDll.IEE_EmoEngineEventGetUserId(hEvent, out userId);
                EmoEngineEventArgs args = new EmoEngineEventArgs(userId);
                EdkDll.IEE_Event_t eventType = EdkDll.IEE_EmoEngineEventGetType(hEvent);
                switch (eventType)
                {
                    case EdkDll.IEE_Event_t.IEE_UserAdded:
                        OnUserAdded(args);
                        break;
                    case EdkDll.IEE_Event_t.IEE_UserRemoved:
                        OnUserRemoved(args);
                        break;
                    case EdkDll.IEE_Event_t.IEE_EmoStateUpdated:
                        EmoState curEmoState = new EmoState();
                        errorHandler(EdkDll.IEE_EmoEngineEventGetEmoState(hEvent, curEmoState.GetHandle()));
                        EmoStateUpdatedEventArgs emoStateUpdatedEventArgs = new EmoStateUpdatedEventArgs(userId, curEmoState);
                        OnEmoStateUpdated(emoStateUpdatedEventArgs);
                        if (!curEmoState.EmoEngineEqual(lastEmoState[userId]))
                        {
                            emoStateUpdatedEventArgs = new EmoStateUpdatedEventArgs(userId, new EmoState(curEmoState));
                            OnEmoEngineEmoStateUpdated(emoStateUpdatedEventArgs);
                        }
                        if (!curEmoState.MentalCommandEqual(lastEmoState[userId]))
                        {
                            emoStateUpdatedEventArgs = new EmoStateUpdatedEventArgs(userId, new EmoState(curEmoState));
                            OnMentalCommandEmoStateUpdated(emoStateUpdatedEventArgs);
                        }
                        if (!curEmoState.FacialExpressionEqual(lastEmoState[userId]))
                        {
                            emoStateUpdatedEventArgs = new EmoStateUpdatedEventArgs(userId, new EmoState(curEmoState));
                            OnFacialExpressionEmoStateUpdated(emoStateUpdatedEventArgs);
                        }
                        lastEmoState[userId] = (EmoState)curEmoState.Clone();
                        break;
                    case EdkDll.IEE_Event_t.IEE_MentalCommandEvent:
                        EdkDll.IEE_MentalCommandEvent_t cogType = EdkDll.IEE_MentalCommandEventGetType(hEvent);
                        switch(cogType){
                            case EdkDll.IEE_MentalCommandEvent_t.IEE_MentalCommandTrainingStarted:
                                OnMentalCommandTrainingStarted(args);
                                break;
                            case EdkDll.IEE_MentalCommandEvent_t.IEE_MentalCommandTrainingSucceeded:
                                OnMentalCommandTrainingSucceeded(args);
                                break;
                            case EdkDll.IEE_MentalCommandEvent_t.IEE_MentalCommandTrainingFailed:
                                OnMentalCommandTrainingFailed(args);
                                break;
                            case EdkDll.IEE_MentalCommandEvent_t.IEE_MentalCommandTrainingCompleted:
                                OnMentalCommandTrainingCompleted(args);
                                break;
                            case EdkDll.IEE_MentalCommandEvent_t.IEE_MentalCommandTrainingDataErased:
                                OnMentalCommandTrainingDataErased(args);
                                break;
                            case EdkDll.IEE_MentalCommandEvent_t.IEE_MentalCommandTrainingRejected:
                                OnMentalCommandTrainingRejected(args);
                                break;
                            case EdkDll.IEE_MentalCommandEvent_t.IEE_MentalCommandTrainingReset:
                                OnMentalCommandTrainingReset(args);
                                break;
                            case EdkDll.IEE_MentalCommandEvent_t.IEE_MentalCommandAutoSamplingNeutralCompleted:
                                OnMentalCommandAutoSamplingNeutralCompleted(args);
                                break;
                            case EdkDll.IEE_MentalCommandEvent_t.IEE_MentalCommandSignatureUpdated:
                                OnMentalCommandSignatureUpdated(args);
                                break;
                            default:
                                break;
                        }
                        break;
                    case EdkDll.IEE_Event_t.IEE_FacialExpressionEvent:
                        EdkDll.IEE_FacialExpressionEvent_t expEvent = EdkDll.IEE_FacialExpressionEventGetType(hEvent);
                        switch (expEvent)
                        {
                            case EdkDll.IEE_FacialExpressionEvent_t.IEE_FacialExpressionTrainingStarted:
                                OnFacialExpressionTrainingStarted(args);
                                break;
                            case EdkDll.IEE_FacialExpressionEvent_t.IEE_FacialExpressionTrainingSucceeded:
                                OnFacialExpressionTrainingSucceeded(args);
                                break;
                            case EdkDll.IEE_FacialExpressionEvent_t.IEE_FacialExpressionTrainingFailed:
                                OnFacialExpressionTrainingFailed(args);
                                break;
                            case EdkDll.IEE_FacialExpressionEvent_t.IEE_FacialExpressionTrainingCompleted:
                                OnFacialExpressionTrainingCompleted(args);
                                break;
                            case EdkDll.IEE_FacialExpressionEvent_t.IEE_FacialExpressionTrainingDataErased:
                                OnFacialExpressionTrainingDataErased(args);
                                break;
                            case EdkDll.IEE_FacialExpressionEvent_t.IEE_FacialExpressionTrainingRejected:
                                OnFacialExpressionTrainingRejected(args);
                                break;
                            case EdkDll.IEE_FacialExpressionEvent_t.IEE_FacialExpressionTrainingReset:
                                OnFacialExpressionTrainingReset(args);
                                break;
                            default:
                                break;
                        }
                        break;
                    case EdkDll.IEE_Event_t.IEE_InternalStateChanged:
                        OnInternalStateChanged(args);
                        break;
                    default:
                        break;
                }
            }
        }