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

  • Thanks to wide spread cloud hosting and innovations small businesses can meet and exceed the legacy systems of goliath corporations. Explore the freedom to work how you want, with a phone system that will adapt to your evolving needs and actually save you lots of expense—read Get an Enterprise Phone System without High Cost and Complexity. The article clearly illustrates: The only hardware you'll need is phone equipment for advanced voice and fax. How to join all your employees, mobile devices, …

  • What does it take to win? According to Jack Welch, winning in business is great because when companies win, people thrive and grow. However, it goes without saying that you have to win the right way -- cleanly and by the rules. Even the most talented businessperson with the best intentions will get nowhere unless he or she knows how to win in today's complex business world. Read this book summary to learn not only the strategies of winning, but also the value that those strategies bring to your professional …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date