MFC / CCriticalSection:简单锁定情况挂起

时间:2010-04-07 23:27:19

标签: c++ winapi mfc multithreading locking

我必须使用MFC / C ++编写一个简单的线程程序,用于单一分配。

我有一个简单的场景,我有一个工作线程,它执行以下行的功能:

UINT createSchedules(LPVOID param)
{
  genProgThreadVal* v = (genProgThreadVal*) param;
  // v->searcherLock is of type CcriticalSection*
  while(1)
  {
    if(v->searcherLock->Lock())
    {
      //do the stuff, access shared object , exit clause etc..
      v->searcherLock->Unlock();
    }
  }
  PostMessage(v->hwnd, WM_USER_THREAD_FINISHED , 0,0);
  delete v;
  return 0;
}

在我的主UI类中,我有一个CListControl,我希望能够访问共享对象(类型为std :: List)。因此锁定的东西。所以这个CList有一个处理函数,如下所示:

void Ccreationprogramme::OnLvnItemchangedList5(NMHDR *pNMHDR, LRESULT *pResult)
{
  LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
  if((pNMLV->uChanged & LVIF_STATE) 
    && (pNMLV->uNewState & LVNI_SELECTED))
  {    
    searcherLock.Lock();
    // do the stuff on shared object
    searcherLock.Unlock();

    // do some more stuff
  }
  *pResult = 0;
}

两个函数中的searcherLock是同一个对象。工作线程函数传递一个指向CCriticalSection对象的指针,该对象是我的对话框类的成员。

一切正常但是,只要我点击我的列表,然后触发处理程序功能,整个程序就会无限期挂起。我尝试使用Cmutex。我尝试使用CSingleLock包装在关键部分对象上,但这些都没有奏效。我错过了什么?

编辑:由于Franci的惊人洞察力,我找到了解决方案。这将教会我不要把所有代码都放在问题中。谢谢!

3 个答案:

答案 0 :(得分:5)

你确定后台主题没有对SendMessageLock之间的用户界限执行Unlock做任何事吗?

如果是,它将被阻塞,直到消息队列处理该消息;但是,消息队列永远不会到达它,因为它在处理列表视图的项目更改通知的过程中被阻止。

答案 1 :(得分:0)

我注意到你在createSchedules()中delete v;。为什么呢?

这让我想知道searcherLock是否真的在两个函数中引用了同一个对象。如果锁不在同一个内存位置,它肯定无法工作。

此外,必须使用正确的状态初始化锁定或关键部分。您没有显示该代码,所以我无法分辨。但如果你没有初始化它,它将会有不好的内容,肯定会破坏。

使用TRACE宏(我认为这是你在MSVC中使用的)进行一些调试,在两个函数中输出&searcherLock(searcherLock的内存位置)以保证它们是同一个对象。

答案 2 :(得分:0)

如果没有看到锁定区域中发生的某些“内容”,则很难验证您的代码是否会从它们中出现。几点建议:

  1. 您的线程可能会锁定关键部分,然后执行引发异常的操作,从而退出并无法解锁。确保使用范围锁定技术不会发生这种情况。

  2. 其中一个关键部分可能根本没有完成。使用调试器并验证预期的行为。