Проблемы с CCriticalSection
От: AndreyPavlov  
Дата: 01.08.06 05:38
Оценка:
Hi,All!
Столкнулся с проблемой. В проге создается thread, который заполняет
VSFlexGrid. Параллельно основной поток обрабатывает события от грида. Для
синхронизации поставил critical section. В произвольный момент происходит
зависание. Написал тестики для VSFlexGrid, MSFlexGrid и ListView — все
аналогично. Вот кусок кода для ListView:


int CMultiThreadTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 if (CListView::OnCreate(lpCreateStruct) == -1)
  return -1;

 AfxBeginThread( MyThreadFunction, this ) ;
 return 0;
}

UINT MyThreadFunction(LPVOID pParam)
{
 CString buf;

 CMultiThreadTestView *t  = (CMultiThreadTestView *)pParam;

 for ( UINT i=0; i<1000; i++ )
 {
  buf.Format("String %d", i+1);

  t->cs.Lock();

  CListCtrl &lst = t->GetListCtrl();
  Sleep(100); //Чего-то делаем
  lst.InsertItem(i, buf);

  t->cs.Unlock();
 }
 return 0;
}


void CMultiThreadTestView::OnMouseMove(UINT nFlags, CPoint point)
{
 cs.Lock();
 //Чего-то делаем
 cs.Unlock();

 CListView::OnMouseMove(nFlags, point);
}


После зависания делаю Break в дибагере. Вижу 2 потока. Основной поток в
строке cs.Lock(); а другой — lst.InsertItem.
Поскажите, что не так!
Re: Проблемы с CCriticalSection
От: Alexey Frolov Беларусь  
Дата: 01.08.06 07:43
Оценка:
Здравствуйте, AndreyPavlov, Вы писали:

AP>Hi,All!

AP>Столкнулся с проблемой. В проге создается thread, который заполняет
AP>VSFlexGrid. Параллельно основной поток обрабатывает события от грида. Для
AP>синхронизации поставил critical section. В произвольный момент происходит
AP>зависание. Написал тестики для VSFlexGrid, MSFlexGrid и ListView — все
AP>аналогично. Вот кусок кода для ListView:


Ситуация очень похожа на deadlock обыкновенный Фактически вы захватили секцию во владение в дополнительном потоке, в основном потоке приходит сообщение WM_MOUSEMOVE которое не может быть обработано и ждет освобождения секции на строчке cs.Lock()
и освободить секцию не предоставляется возможным так как в доп потоке вы делаете ::SendMessage(m_hWnd, LVM_INSERTITEM, 0, (LPARAM)pItem); которое становится в ту же очередь и будет обработано после WM_MOUSEMOVE — это deadlock. Не стану сразу утверждать, но кажется что тут вообще не надо использовать объекты синхронизации. Во всяком случае InsertItem не следует заворачивать внутрь, с этой синхронизацией должен справиться оконный диспетчер сообщений. А вообще почитайте про функции SendMessage, PostMessage, SendMessageTimeout
Re: Проблемы с CCriticalSection
От: Георгиевич Россия  
Дата: 01.08.06 07:54
Оценка:
AP>Столкнулся с проблемой. В проге создается thread, который заполняет
AP>VSFlexGrid. Параллельно основной поток обрабатывает события от грида. Для
AP>синхронизации поставил critical section. В произвольный момент происходит
AP>зависание. Написал тестики для VSFlexGrid, MSFlexGrid и ListView — все
AP>аналогично. Вот кусок кода для ListView:
AP>После зависания делаю Break в дибагере. Вижу 2 потока. Основной поток в
AP>строке cs.Lock(); а другой — lst.InsertItem.
AP>Поскажите, что не так!

Важно увидеть не просто два потока, а состояние deadlock'а

1. Самое важное и почему прекращается работа вашего приложения:
Не нужно блокировать основной поток приложения. Тот, который занимается выгребанием сообщений. Потому что эти сообщения приложению нужно обрабатывать, и Windows нужно знать "реакцию" приложения на посылаемые ей сообщения.
Эту реакцию система узнает через постоянно вызываемые приложением функции WinAPI, к примеру DefWindowProc().

2. Все контролы MS Windows — Thread Safe. Они управляются посылкой сообщений (Winapi-функцией SendMessage()) а этот механизм по определению пересекает адресные пространства и не нуждается ни в какой синхронизации, поток дернувший SendMessage() будет заблокирован пока контрол не обработает это сообщение.
MFC классы аналогично, практически везде thread safe (нужно смотреть исходники MFC что именно мы делаем).

3. Правильно разработанные ActiveX-контролы внутри себя тоже Thread Safe.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.