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

  • On-demand Event Event Date: October 29, 2014 It's well understood how critical version control is for code. However, its importance to DevOps isn't always recognized. The 2014 DevOps Survey of Practice shows that one of the key predictors of DevOps success is putting all production environment artifacts into version control. In this webcast, Gene Kim discusses these survey findings and shares woeful tales of artifact management gone wrong! Gene also shares examples of how high-performing DevOps …

  • Today's agile organizations pose operations teams with a tremendous challenge: to deploy new releases to production immediately after development and testing is completed. To ensure that applications are deployed successfully, an automatic and transparent process is required. We refer to this process as Zero Touch Deployment™. This white paper reviews two approaches to Zero Touch Deployment--a script-based solution and a release automation platform. The article discusses how each can solve the key …

Most Popular Programming Stories

More for Developers

RSS Feeds