我要做一个动画效果,采用定时刷新绘图的方式。采用定时器刷新绘图的方式以前我用过,这里不想用了,改而用线程的工作方式。最初我在动画开始函数OnStart()中启动我创建的一个线程,同时把窗口句柄赋给该线程,然后在线程中循环发送图片序号以消息方式传给窗口句柄所在类的绘图函数,这样便实现了动画效果,经过检验也成功了。
  现在进行改动后,出现了毛病。由于程序的需要,我的代码进行了扩充,在启动动画的OnStart函数中使用了一个while死循环语句,循环里面有一些条件判断,当满足某个条件时启动改动前我创建的那个线程,仍然是把消息窗口句柄赋给该线程,线程内部函数也基本不变,由于线程不会等待,会接着原有程序继续向下执行,所以我想这就相当于同时开启了两个程序,应该互不影响,但是发现此时不再绘图了,做不出来动画效果了。我考虑了一下,因为线程里面最初用的是SendMessage,而SendMessage是同步消息机制,即程序1调用2时,1停下不动,直到2完成后回到1,1才继续执行下去,可能线程发送消息后消息没有立即执行产生了阻塞,所以我便改成了异步消息机制的PostMessage,希望两个程序各自执行自己的,互不影响,可是改成PostMessage后还没有成功,调试时我发现每次都执行到PostMessage后就没有动静了,难不成是因为OnStart函数中while循环一直执行,窗口句柄一直进行操作无暇兼顾线程中发送过来的消息?
附部分代码说明:
void CMyView::OnStart()
{
     HWND  hwnd=GetSafeHwnd(); //接收消息的窗口句柄
     DWORD dwthread;
     ::CreateThread(NULL,0,CartoonThread,hwnd,0,&dwthread);
}DWORD WINAPI CartoonThread(LPVOID lpParameter)
{
HWND hHwnd = (HWND)lpParameter;
while (NumberOfBitmap!=11)  //NumberOfBitmap是我定义的一个外部变量,用来标记图片序号
{
::PostMessage(hHwnd,WM_CARTOON,NumberOfBitmap,NULL);
Sleep(100);
NumberOfBitmap++;
}
                NumberOfBitmap=0;
                return 0;
}//WM_CARTOON是我自建的一个绘图消息
LRESULT CMyView::OnCartoon(WPARAM wParam,LPARAM lParam)
{
int Number=(int)lParam;
CClientDC dc(this);
BITMAP BM;
CDC MemDC;
CRect rect;
CBitmap bitmap;

bitmap.LoadBitmap(IDB_BITMAP1 + Number); //加载我创建的位图资源 GetClientRect(&rect);
MemDC.CreateCompatibleDC(NULL);
MemDC.SelectObject(&bitmap);
bitmap.GetObject(sizeof(BM),&BM);
bitmap.GetBitmap(&BM);

dc.BitBlt(0, 0, 150, 150, &MemDC, 0, 0, SRCCOPY); return 0;
}改动后,
         void CMyView::OnStart()
           {
                  while (1)
 {
    if (Cartoon)  //Cartoon是我标记的一个外部bool变量
     {
          HWND  hwnd=GetSafeHwnd(); //接收消息的窗口句柄
                          DWORD dwthread;
                          ::CreateThread(NULL,0,CartoonThread,hwnd,0,&dwthread);
          Cartoon=FALSE;
      }
                    ……
 }
           }DWORD WINAPI CartoonThread(LPVOID lpParameter)
{
HWND hHwnd = (HWND)lpParameter;
while (NumberOfBitmap!=11)  //NumberOfBitmap是我定义的一个外部变量,用来标记图片序号
{
::PostMessage(hHwnd,WM_CARTOON,NumberOfBitmap,NULL);
Sleep(100);
NumberOfBitmap++;
}
                NumberOfBitmap=0;
                Cartoon=TRUE;
                return 0;
}
  另外,下一步,我还想将程序体改成这样的结构,OnStart函数中启动一个主线程,之前的while死循环语句位于这个线程内,循环语句中仍然有一些条件判断,当满足某些条件时,再启动一个子线程,但子线程执行时主线程挂起,也就是while循环语句执行到某个启动子线程语句时先停住,当子线程执行完毕后再返回主线程,主线程恢复并接着执行启动子线程后面的语句。可是这样一来的话,我觉得自己写的程序就像函数调用了,因为主函数调用子函数,子函数不执行完毕返回的话主函数是不会继续执行下去的,而线程是不会等待的,会在启动后接着在源程序向下继续执行,这就给我带来了疑惑。
  所以这里我想向大侠们请教下,帮我解决这几个问题:
   1、我利用线程做动画效果改动后失败的原因在哪里,是不是如我所想象的那样?
    2、我之前利用定时器绘制动画时,曾经在while死循环中调用定时器,同样也不会绘图。有位大侠告诉我定时器
       SetTimer 执行后窗口会收到WM_TIMER消息,但是我的while一直是死循环,定时器消息是不会响应执行的,非退出
       while循环,这个定时器不执行的原因我想大概跟我用线程做动画传递消息失败的原因一样的吧,因为SetTimer的第一
       个参数也是消息窗口句柄?
    3、利用线程实现类似函数调用的工作模式该如何操作?这一点请说明详细一些,因为我现在线程部分看的还不很深入,
       所以有代码说明更好。
       如果有好的例子可以更好的解释,也可以发送至我邮箱:[email protected]
  最后向认真回帖指导的大侠表示诚挚的谢意!

解决方案 »

  1.   

    while(1)里面 加个 sleep 如何?
      

  2.   

    void CMyView::OnStart()
      {
      while (1)
    {
    if (Cartoon) //Cartoon是我标记的一个外部bool变量
    }
    }
    这个Cartoon消息怎么传进来?OnStart不是主线程执行的吗?
      

  3.   

    你在OnStart()里用死循环
    主线程不直接挂起了
      

  4.   

    1、我利用线程做动画效果改动后失败的原因在哪里,是不是如我所想象的那样?
    --------------------------------------------------------------------
    你在线程中做和绘图无关的东西,主要是一些复杂的计算,计算完成以后发送消息到主窗口,主窗口去绘图动态更新界面2、我之前利用定时器绘制动画时,曾经在while死循环中调用定时器,同样也不会绘图。有位大侠告诉我定时器
      SetTimer 执行后窗口会收到WM_TIMER消息,但是我的while一直是死循环,定时器消息是不会响应执行的,非退出
      while循环,这个定时器不执行的原因我想大概跟我用线程做动画传递消息失败的原因一样的吧,因为SetTimer的第一
      个参数也是消息窗口句柄?
    -----------------------------------------------------
    你在主线程用使用while(1)死循环,那么界面很可能会卡住,那么你的其他的消息,比如WM_PAINT也来不及响应,另外WM_TIMER和WM_PAINT都是优先级比较低的消息,只有当线程中没有其他待处理的消息的时候才会去处理它们,可见如果当前有存在复杂的计算的话,WM_TIMER/WM_PAINT很可能会来不及响应,导致延迟,所以还是建议用线程来代替。  3、利用线程实现类似函数调用的工作模式该如何操作?这一点请说明详细一些,因为我现在线程部分看的还不很深入。
    #define UM_MSG WM_USER+11 //自定义消息
    volatile BOOL bExitThread = FALSE; // 或者用内核事件对象AfxBeginThread(ThreadProc, (LPVOID)GetSafeHwnd());//创建线程,执行后台计算UINT __cdecl ThreadProc(LPVOID lParam)
    {
     HWND hWnd = (HWND)lParam;
     ASSERT(hWnd);
     while(!bExitThread)
     {
      //执行计算,并将数据结果发送到主界面,通知其去更新
     ::SendMessage(hWnd, UM_MSG, (WPARAM).., (LPARAM)...);
     }
     return 0;
    }afx_msg LRESULT HandleUserMsg(WPARAM wParam, LPARAM lParam);BEGIN_MESSAGE_MAP(...,...)
    ...
    ON_MESSAGE(UM_MSG, CXX::HandleUserMsg)
    END_MESSAGE_MAP()LRESULT CXX::HandleUserMsg(WPARAM wParam, LPARAM lParam)
    {
     ...
     ...//得到数据,然后刷新,绘制图形,比如Invalidate();
     return 0;
    }
      

  5.   

    if (Cartoon) //Cartoon是我标记的一个外部bool变量
    问题就在这.Cartoon是static类型吧?
    编译器不会想到变量会自行改变,他只mov eax Cartoon一次,然后不停的test eax eax, jz xxxx,就算你在别的线程里改变他也不管.
    把Cartoon声明为voliate就可以了,这表示变量是不稳定的,编译器就不会对此变量做任何优化.
    但是不建议这样做.循环锁是个很笨的东西.