Implementing Asynchronous Data Transfer for COM Clients

The demo for this article was built and compiled on Windows 98 using Visual C++ 6.0. To build the demo, load the async client project and do a complete build. This should also build the COM server project at the same time. You can test the demo by clicking the Asynchronous Request button and performing user actions such moving the window around, displaying a message box and minimizing or closing the window.

If you have a situation when you need to get data from a com server that may take an undetermined amount of time and you require your user interface to respond to user commands during this time, this article is for you. It discusses and provides a mechanism for asynchronous data transfer when retrieving data from a COM server. The basic idea is to provide a base class, which I call CAsyncClass, that you inherit from, which will create a separate thread for the data retrieval and override the windows message loop while waiting for the data to return. The following steps outline how to use the CAsyncClass functionality.

1. Add the files async.h and async.cpp to your project.

2. Create and inherit a new class from CAsyncClass.

3. Add data members in your new class to hold the values returned from your com server calls.

4. Optional: Add a Get/Set methods for your data members.

5. Add an OnNotify method to your client inorder to extract the data from your class.

6. Override the virtual method CAsyncClass::OnNotifyComplete to call the OnNotify method when the synchronous data transfer is complete.

7. Override the virtual method OnRequestData to CREATE an interface to your com server object and request your data. NOTE: By the time OnReqestData is called, it will be operating in a separate thread. You cannot use an existing interface that was created in another thread.

8. Add a method in your client to call CAsyncClass::DoRequestData.

EXAMPLE

//////////////////////////////////////////////////////////////////////
// CDemoClass sample class used in this demo

class CDemoClass :public CAsyncClass
{
// Construction
public:
  CDemoClass(CAsyncclientDlg* pOwner)
    :CAsyncClass() 
  {
    m_pOwner=pOwner; 
  }

// Attributes
private:
  _bstr_t           m_bstrData;
  CAsyncclientDlg*  m_pOwner;

// Operations
public:
  _bstr_t&  GetData()               { return m_bstrData; }	
  void      SetData(_bstr_t& bstr)  { m_bstrData=bstr;   }	

// Operations
public:
  void OnNotifyComplete() { m_pOwner->OnDemoNotify(); }
 
  void OnRequestData()
  {
    try
    {
      IasyncProducerPtr p(_T("Asyncserver.asyncProducer.1"));
      SetData(p->GetAsyncData());	
    }
    catch(_com_error &e)
    {
      SetError(e.Error());
    }
  }
};

//////////////////////////////////////////////////////////////////////
// The client window used in this demo

void CAsyncclientDlg::OnDemoNotify() 
{ 
  DWORD dwError=m_pDemoClass->GetError();

  if(dwError)
    m_sReturn.Format(_T("Error %d"),dwError); 
  else
    m_sReturn=(LPTSTR)m_pDemoClass->GetData();

  UpdateData(FALSE); 
}

void CAsyncclientDlg::OnAsyncButton() 
{
  m_sReturn.Empty();

  UpdateData(FALSE);

  if(m_pDemoClass)
    m_pDemoClass->DoRequestData();
}

Download demo project - 68 KB

Download source code - 2 KB

Date Last Updated: May 17, 1999



Comments

  • thread unsafe method

    Posted by Legacy on 09/28/2000 12:00am

    Originally posted by: Alex Zelinsky

    Following example is not thread safe. You are trying
    
    m_bComplete flag in both AsyncTread and current thread
    with no critical section, etc. It would be better to try MsgWaitForMultipleObjects or Win Events (can wait for it each time the code enters msg loop - very small time out should be used).

    void CAsyncClass::DoRequestData()
    {
    m_dwError=0L;
    m_bComplete=false;

    HANDLE hThread;
    DWORD dwThreadID;

    hThread=CreateThread(NULL,0,AsyncThread,(LPVOID)this,0,&dwThreadID);

    bool bQuit=false;

    while(!m_bComplete)
    {
    MSG msg;
    while(!bQuit && PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))
    {
    bQuit=(bQuit || msg.message==WM_QUIT);

    if(msg.message!=WM_QUIT)
    {
    if(GetMessage(&msg,NULL,0,0)>0)
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    }
    }
    }

    WaitForSingleObject(hThread,INFINITE);
    CloseHandle(hThread);

    if(!bQuit)
    OnNotifyComplete();
    }

    Reply
  • Solution only for COM not for DCOM

    Posted by Legacy on 09/24/1999 12:00am

    Originally posted by: Michael Setzer

    This solution only works with COM on one machine because there will be a Windows message used to notify the client.

    Is there an other possibility which will also work with DCOM?
    I think there must be one, which will work like a call back function, but i haven't found an example yet. It should also work in a MFC application.

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

Top White Papers and Webcasts

  • The latest release of SugarCRM's flagship product gives users new tools to build extraordinary customer relationships. Read an in-depth analysis of SugarCRM's enhanced ability to help companies execute their customer-facing initiatives from Ovum, a leading technology research firm.

  • Live Event Date: May 6, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT While you likely have very good reasons for remaining on WinXP after end of support -- an estimated 20-30% of worldwide devices still are -- the bottom line is your security risk is now significant. In the absence of security patches, attackers will certainly turn their attention to this new opportunity. Join Lumension Vice President Paul Zimski in this one-hour webcast to discuss risk and, more importantly, 5 pragmatic risk mitigation techniques …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds