DLL_Callback: Sample for asyncronous inner-process operations.

Environment: VC6 SP3, VB6 SP3

This sample demonstrates the use of asyncronous inner-process operations.
In this case we have an app that wants to get data from a DB,
which could take a undefined long amount of time.
The app wants to do other work while waiting for the result of the DB-Call.
It calls the "GetDBData()"-function, which returns immediately.
After the DLL-function has done its work, it notifies the caller app
via the CALLBACK-function "DataReadNotify()".

A VB sample which uses this DLL with VB can be found in the "VB_Sample"-Path.

Library Source:

DLL_Callback.h
#ifndef _DLL_CALLBACK_
#define _DLL_CALLBACK_

// All declarations which are needed resides in "windows.h"
#include <windows.h>

// Placeholder for function-export macros
#define LIBRARY_EXPORT __declspec(dllexport) __cdecl

// Function Declarations for Static Export
extern "C" {
long LIBRARY_EXPORT GetDBData(void);
long LIBRARY_EXPORT SetCallbackProcAddr(long);
}

// Function Declaration for Callback function 
// of the Calling App
typedef void (* TDataReadNotify)(long);

#endif
DLL_Callback.cpp
// Comment out the line below, if you want STDCALL 
// for the VB-Example.
#define CDECL_CALLING_CONVENTION

#ifdef CDECL_CALLING_CONVENTION
  #include "DLL_Callback.h"
#else
  #include "DLL_Callback_StdCall.h"
#endif

// Vars for Imported Functions
TDataReadNotify DataReadNotify;
HANDLE hThread;
DWORD pThreadId;

DWORD DoTheWork(LPVOID lpParameter)
{
  long lDBData;

// Doing stuff that takes 5 sec., i.e. reading DB Data.
// ...
  Sleep(5000);
  lDBData = 123;
// ...

// Notify the caller app via CB-function.
  if (DataReadNotify != NULL) DataReadNotify(lDBData);

  return 0;
};

long LIBRARY_EXPORT GetDBData(void)
{
  long lProcAdr;

// Get ProcAddress for Thread-Func and create/run the thread.
  lProcAdr = (long)(&DoTheWork);
  hThread = CreateThread(NULL, 
                         0,
                         (LPTHREAD_START_ROUTINE)lProcAdr,
                         NULL,
                         0,
                         &pThreadId);

// Return to caller app.
  return 0;
};

long LIBRARY_EXPORT SetCallbackProcAddr(long lProcAddress)
{
  long Result = 0;

// Set the Proc-Address for the notify-func of 
// the caller app.
  DataReadNotify = (TDataReadNotify)lProcAddress;

  if (DataReadNotify != NULL) Result = 1;
  return Result;
};

C++ Sample Source:

Callback_Sample.h

#ifndef _CALLBACK_SAMPLE_
#define _CALLBACK_SAMPLE_

// All declarations which are needed resides
// in "windows.h"
#include <windows.h>

// Placeholder for function-import macros
#define LIBRARY_IMPORT __declspec(dllimport) __cdecl

// Function Declarations for Static 
//      Import (aka "Implicied Linking")
// This requires the Output-LIB of the DLL_Callback Library.
extern "C" {
int   LIBRARY_IMPORT GetDBData(void);
int   LIBRARY_IMPORT SetCallbackProcAddr(long);
}

#endif
Callback_Sample.cpp
#include "Callback_Sample.h"

int iWait = 1;
char sDBData[11];
char sMessage[64];

void DataReadNotify(long lDBData)
{
  _ltoa(lDBData, sDBData, 10);
  strcpy(sMessage, "DBData from DLL is: ");
  strcat(sMessage, sDBData);
  ::MessageBox(0, sMessage, 
               "Sample App", MB_OK + MB_ICONINFORMATION);
// Set Wait to 0, so that WinMain can go further.
  iWait = 0;
};

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
  long lProcAdr;

// Get Address-Pointer of the CB-function
  lProcAdr = (long)(&DataReadNotify);
// Send Address-Pointer Information to the DLL
  SetCallbackProcAddr(lProcAdr);
// Call the function of the DLL, which reads DB-Info 
// or something else.
  GetDBData();

// Do other work while the DLL reads the DBData
// ...
// I.e.: Show a splash-screen, write values to an 
//       INI-File or whatever
// ...

// if the DLL-function is still busy, loop until 
// the DLL notifies via the CALLBACK-function "DataReadNotify()".
  while (iWait) {};

  return 0;
};

Downloads

Download source including VC/VB demo project - 10 KB


Comments

  • helpful article

    Posted by ricky_cpp on 12/10/2008 07:11am

    Thanks..this article has helped in undestanding concept of callbacks in windows :-)

    Reply
  • DLL_Callback: Sample for asyncronous inner-process operations.

    Posted by Legacy on 10/21/2002 12:00am

    Originally posted by: Suman Bhattacharya

    This is working fine when running from VB IDE.But it fails after creating exe.It raises an error like "Unable to read from memory".I am doing a project which requires this sort of callback operation. This is an ergent requriement.Pls help me.

    Reply
  • VB Crashing (Only code chg i was __stdcall) help!

    Posted by Legacy on 08/08/2002 12:00am

    Originally posted by: Mr Unlucky

    It runs and returns the value and the message box appears with the value then Crash! vb completely crashes. Does anyone know why?

    please help thanks.

    Environment
    VC6 No Service Pack / SP5
    VB6 No Service Pack / SP5

    Reply
  • callback

    Posted by Legacy on 08/02/2002 12:00am

    Originally posted by: St.Daniel

    i realy dont get it

    Reply
  • Thread not need ..

    Posted by Legacy on 03/30/2002 12:00am

    Originally posted by: krkim

    The Main Program is holding until the GetData() thread function routine to be end,
    while (iWait) {}; cause this probelm..
    so,thread routine is not meaning.


    Reply
  • Not a good idea ...

    Posted by Legacy on 03/28/2002 12:00am

    Originally posted by: Robert Simpson

    I highly recommend NOT using this method with VB.

    The callback function is executed from a different thread than the thread that called GetDBData(), and no marshaling is done because this code runs in the absence of COM. VB is designed around COM, and VB's behavior will be erratic at best. Depending on what is done in the callback routine, your VB app may crash hard. Do NOT call any methods on any COM classes (in VB, all apps are COM classes, even the private ones), and take care not to do anything involving COM in the callback. It may work, but it breaks the fundamental rules of COM and is a huge no-no, especially if you want a stable, reliable application.

    Also ... The DoTheWork() function is declared as:

    DWORD DoTheWork(LPVOID lpParameter)

    This is incorrect. It should be declared as:

    DWORD WINAPI DoTheWork(LPVOID lpParameter)

    ThreadProc()'s require the entry point to be _stdcall.

    Robert Simpson
    Programmer at Large
    Black Castle Software, LLC

    Reply
  • It's useful,but...

    Posted by Legacy on 06/05/2001 12:00am

    Originally posted by: haopf

    hi,
    This method is useful to me,but how can i pass a pointer
    of buffer in vc++ to vb call back function? If i use a int*
    pointer parameter,vb can't read data form it.

    Reply
  • New bie!?

    Posted by Legacy on 05/12/2001 12:00am

    Originally posted by: Saad

    Funny I don't see what the big deal is about this crap ?
    Good Luck fella!

    Reply
  • Welcome!

    Posted by Legacy on 05/08/2001 12:00am

    Originally posted by: Sergey

    At least one Programmer finally realized the life is much easier without COM/COM+/DCOM/.NET

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • The impact of a data loss event can be significant. Real-time data is essential to remaining competitive. Many companies can no longer afford to rely on a truck arriving each day to take backup tapes offsite. For most companies, a cloud backup and recovery solution will eliminate, or significantly reduce, IT resources related to the mundane task of backup and allow your resources to be redeployed to more strategic projects. The cloud - can now be comfortable for you – with 100% recovery from anywhere all …

  • Ever-increasing workloads and the challenge of containing costs leave companies conflicted by the need for increased processing capacity while limiting physical expansion. Migration to HP's new generation of increased-density rack-and-blade servers can address growing demands for compute capacity while reducing costly sprawl. Sponsored by: HP and Intel® Xeon® processors Intel, the Intel logo, and Xeon Inside are trademarks of Intel Corporation in the U.S. and/or other countries. HP is the sponsor …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds