antoniozhou的Blog

流媒体技术,服务器技术,多媒体网络应用

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

      最近正在忙着开发一款三维CAD系统。BOSS希望该CAD系统具备文档自动保存功能,就像Office系列软件一样,在用户不知不觉的情况下将其所作修改进行保存,这样可以防止在意外宕机情况下用户的操作丢失。

      其实添加自动保存功能并不是一件非常困难的事情,最简单的情况就是设置Timer计时器,捕捉系统消息WM_TIMER,并在Timer的响应函数里调用CDocument::OnSaveDocument()函数,使用主线程进行文档保存。不过,这样做是有弊端的。例如在我们所要做的CAD系统中,在实际使用过程中,可能会出现数据量非常庞大的零部件或组装结构。如果在这种情况下使用主线程来保存文档,文档的保存时间可能会较长。而在文档保存的过程中,系统会将光标设置为等待,因此,不仅无法再对文档进行操作,即使能操作,也会因为主线程正在忙碌状态而使系统无法响应用户操作,势必影响使用。

      一个较好的方法就是使用辅助工作线程来进行文档的保存工作。由于工作线程只在后台运行,与主线程相对独立,因此,可以较好地解决用户操作与文档保存的并行问题。虽然在单核CPU情况下,所谓的多线程仍然存在CPU使用上的等待与交替过程,但由系统强制分配的CPU使用时间保证了两种操作形式上的并行,基本上解决了问题。

      另外需要强调的是,由于MFC类库中的CDocument类在使用过程中,其内部函数与主线程存在线程依赖关系。具体是由一个Map影射造成的,因此如果使用传递给工作线程处理函数的CDocument类型指针直接调用CDocument::OnSaveDocument()则会造成程序断言失败而意外退出。下面是windows核心代码wincore.cpp内部包含的一个原函数。

void CWnd::AssertValid() const
{
 
if (m_hWnd == NULL)
  
return;     // null (unattached) windows are valid

 
// check for special wnd??? values
 ASSERT(HWND_TOP == NULL);       // same as desktop
 if (m_hWnd == HWND_BOTTOM)
  ASSERT(
this == &CWnd::wndBottom);
 
else if (m_hWnd == HWND_TOPMOST)
  ASSERT(
this == &CWnd::wndTopMost);
 
else if (m_hWnd == HWND_NOTOPMOST)
  ASSERT(
this == &CWnd::wndNoTopMost);
 
else
 
{
  
// should be a normal window
  ASSERT(::IsWindow(m_hWnd));

  
// should also be in the permanent or temporary handle map
  CHandleMap* pMap = afxMapHWND();
  ASSERT(pMap 
!= NULL);

  CObject
* p;
  ASSERT((p 
= pMap->LookupPermanent(m_hWnd)) != NULL ||
   (p 
= pMap->LookupTemporary(m_hWnd)) != NULL);
  ASSERT((CWnd
*)p == this);   // must be us

  
// Note: if either of the above asserts fire and you are
  
// writing a multithreaded application, it is likely that
  
// you have passed a C++ object from one thread to another
  
// and have used that object in a way that was not intended.
  
// (only simple inline wrapper functions should be used)
  
//
  
// In general, CWnd objects should be passed by HWND from
  
// one thread to another.  The receiving thread can wrap
  
// the HWND with a CWnd object by using CWnd::FromHandle.
  
//
  
// It is dangerous to pass C++ objects from one thread to
  
// another, unless the objects are designed to be used in
  
// such a manner.
 }

}




      注意看上述代码的注释部分。由于CDocument::OnSaveDocument()函数进行了较高层封装,与线程相关,因此,CDocument::OnSaveDocument()函数需要重写。在重写的过程中,不能再继承CDocument::OnSaveDocument()函数,而需要从更低层着手写保存操作。

关于辅助工作线程的使用方法,我会在稍后的时间里贴出程序代码和注释,敬请关注!

posted on 2006-08-15 11:32  antoniozhou  阅读(3739)  评论(5编辑  收藏  举报