multithreaded OCX


I wrote a multithreaded OCX (Visual C++, with the ocx wizzard).

In a second thread (buffer processing) I fire an event to tell the application that someting has to be processed. The application then call's a property, set by the OCX before firing the event.

A Visual C++ application test programm gets the correct values and runs perfect. However, a VB programm crashes when asking the property in the eventhandling. (It does not crash when it asks the property value outside the event-handling!!)

Here's some OCX code :

- creation of the second thread

      AfxBeginThread((AFX_THREADPROC)BufferThread, this);

- the second thread

UINT BufferThread (LPVOID pParam)
      CPosKeyboardCtrl* pObject = (CPosKeyboardCtrl*)pParam;    

      if (pObject == NULL ||
            return 1;   // if pObject is not valid    // do something with 'pObject'

      while (pObject->m_bOpened)
            // wait until character is received
        WaitForSingleObject(hEventReceive, INFINITE);
            while (pVerwerkBuffer < pCurrentBuffer)
                  // we have characters to process
                  pObject->m_pOSKeyData = TheKey;
                  pVerwerkBuffer ++;
            pVerwerkBuffer = pBeginGlobalBuffer;
            pCurrentBuffer = pBeginGlobalBuffer;
      return TRUE;

I am desperate. Why does the C++ testprogramm work, but not a VB programm?

A correct and usable answer please.

Who is Participating?
pellepConnect With a Mentor Commented:
I've had precisely your problem. The problem lies in the fact that vb doesn't support multithreading to the full extent. This will result in a GPF when you try to fire an event in a second thread of your component. Solve this by only firing events from the main thread of your OCX. It's all described in the article below. Go to and search for 'Q196026'. Their proposed sollution involves sending windows messages to your main thread (and it worked fine for me).
In the second thread, do:
(the arg list is arbitrary
WM_EVENT_ERROR must be defined to for instance (WM_USER+101)
void SecondThreadClass::FireEvent(int iNum, int iSeverity, LPCTSTR lpszDesc, LPCTSTR lpszSource)
      void **pArgs = new LPVOID[4];
      pArgs[0] = new char[strlen(lpszDesc) + 1];
      strcpy((char*)pArgs[0], lpszDesc);
      pArgs[1] = new char[strlen(lpszSource) + 1];
      strcpy((char*)pArgs[1], lpszSource);
      pArgs[2] = new int(iNum);
      pArgs[3] = new int(iSeverity);
      PostMessage(WM_EVENT_ERROR, (long)pArgs);
In the main thread, add a msg map and bind the WM_EVENT_ERROR to a handler function like:

LRESULT MyMainThreadClass::OnFireError(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
      //0 = Description (LPCTSTR)
      //1 = Source (LPCTSTR)
      //2 = Number (int*)
      //3 = Severity (int*)

      void **pArgs = (void**)wParam;

        BSTR sDesc;
      BSTR sSource;
      WCHAR   wszBuff[512];            

      if (MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)pArgs[0], -1, wszBuff, 512)==0)
            return 0;
      sDesc = SysAllocString(wszBuff);

      if (MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)pArgs[1], -1, wszBuff, 512)==0)
            return 0;
      sSource = SysAllocString(wszBuff);
      if ((sDesc == NULL) || (sSource == NULL))
            return 0;
//This would be your ordinary event
//firing function
      Fire_Error(*(int*)pArgs[2],*(int*)pArgs[3], sDesc, sSource);
      delete[] pArgs[0];
      delete[] pArgs[1];
      delete pArgs[2];
      delete pArgs[3];
      delete[] pArgs;
      return 0;

Good luck

See MSDN article 'PRB: Firing Event in Second Thread Causes IPF or GPF'
ID: Q196026

johanhzAuthor Commented:

Your suggestion led me to the sollution (article ID Q157437), so i'm giving you the points.

Thanks and enjoy!
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.