Solved

multithreaded OCX

Posted on 2000-04-07
3
620 Views
Last Modified: 2012-06-21
Hi,

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 ||
      !pObject->IsKindOf(RUNTIME_CLASS(CPosKeyboardCtrl)))
            return 1;   // if pObject is not valid    // do something with 'pObject'

      while (pObject->m_bOpened)
      {
        ResetEvent(hEventReceive);
            // wait until character is received
        WaitForSingleObject(hEventReceive, INFINITE);
            
            while (pVerwerkBuffer < pCurrentBuffer)
                  // we have characters to process
            {
                  pObject->m_pOSKeyData = TheKey;
                  pVerwerkBuffer ++;
      pObject->FireDataEvent(1);
            }
            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.

JOHan
0
Comment
Question by:johanhz
3 Comments
 
LVL 14

Expert Comment

by:AlexVirochovsky
Comment Utility
0
 
LVL 4

Accepted Solution

by:
pellep earned 600 total points
Comment Utility
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 microsoft.com 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)
{
            //ARGS
      //0 = Description (LPCTSTR)
      //1 = Source (LPCTSTR)
      //2 = Number (int*)
      //3 = Severity (int*)

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


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

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

      //SOURCE
      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;
      SysFreeString(sDesc);
      SysFreeString(sSource);
      return 0;
}

Good luck

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

0
 

Author Comment

by:johanhz
Comment Utility
pellep,

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

Thanks and enjoy!
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now