Problem mit Thread (evtl: ListCtrl schuld?)

Hallo,

folgendes Problem :
Ich habe einen Thread, doch irgendwie scheint sich etwas zu verklemmen.

Beschreibung des Programms:
Mein Thread ändert zyklisch die Beschriftung der Zeileninhalte einer ListrCtrl (Diese hat insgesamt nur 4 Zeilen).

Problem:
Wenn ich wild an der Oberfläche herumklicke bleibt das Programm hängen!

Mit wild herumklicken meine ich zB: Schnelles öffnen/schließen eines Popup-Menüs (erscheint beim Klicken auf meine Toolbar) oder einfach mal lange Mausklicks auf die Oberfläche etc…

Hinweis
Mein Programm ist zwar für embedded Visual C++ (für PDA), aber vielleicht weiß ja jemand hier auch einen Rat.

FRAGE
Hängt das vielleicht mit dem schnellen umändern der Listenzeile mittels SetItemText zusammen? Manchmal erwischt man anscheinend einen Zeitpunkt wo sich das System „aufhängt“. Vielleicht löst SetItemText intern irgendwelche MFC-Messages aus auf deren Antwort gewartet werden muss, und gleichzeitig werden auch Windows-Messages beim Öffnen des Popup-Menüs erzeugt, auf deren Abarbeitung gewartet werden muss (Liste wird ja über Thread upgedatet)

Code
Mein Thread ist eine statische private Methode meiner Klasse und wird wie folgt aufgerufen:

void CMyClass::StartThread(void)
{
 // Anweisungen ...

 AfxBeginThread(ThreadProc, this, THREAD\_PRIORITY\_NORMAL);

 // Anweisungen ...
}

Hier der Quellcode des Threads und der Methode zum Upaten der ListCtrl:

UINT CMyClass::ThreadProc(LPVOID pParam)
{
 CMyClass\* pView = (CMyClass\*) pParam;
 ASSERT(pClass);

 while(!pClass-\>m\_bThreadStopped)
 {
 // Anweisungen ...

 // Aufruf einer Methode welche die ListCtrl von CMyClass updatet

 pClass-\>UpdateList();

 // Anweisungen ...
 }

 ExitThread(0);
 return 0;
}


void CMyClass::UpdateList(void)
{
 // Anweisungen ...
 
 // Aktuelle betrachteten Eintragder Liste updaten, also
 // den Beschriftungstext ändern
 // m\_pMyList ist von ListCtrl abgeleitet

 m\_pMyList-\>UpdateItem(m\_nCurrentItem, strNewItemText)
 
 // Anweisungen ...
}

Hier der wichtige Code der von ListCtrl abgeleiteten Klasse

void CMyListCtrl::UpdateItem(int nItem, CString strItemText)
{
 // Neuen String auf dem Heap erzeugen. Weiß ja nicht wann die 
 // Nachrichtenbehandlung erfolgt in welcher der String gebraucht wird.

 CString\* pStrItemText= new CString(strItemText);

 // Die Nachricht WM\_UPDATE\_ITEM benutzerdefiniert
 // Nachricht versenden, damit das ausführen des Listupdates im
 // "Hauptthread" stattfindet

 PostMessage(WM\_UPDATE\_ITEM, (WPARAM) nItem, (LPARAM) pStrItemText);
}


LRESULT CMyListCtrl::open\_mouth:nUpdateItem(WPARAM wParam, LPARAM lParam)
{
 int nIndex = (int) wParam;
 CString \*pStrItemText= (CString \*) lParam;

 SetItemText(nIndex , 0, \*pStrItemText);

 // Speicher auf dem Heap wieder frei geben

 delete pStrItemText;

 return 0L;
}

Durch das Senden der Nachricht WM_UPDATE_ITEM wird der Update der Liste im „Hauptthread“, welcher „Besitzer“ der Oberflöche ist, durchgeführt.

Weiß keinen Rat warum mein Programm hängen bleibt und bin für jede Bemerkung/Hilfe dankbar!

Vielen Dank,
Gruß Tom

Hallo Tom,

du mußt jeden Zugriff auf m_pMyList mit einer Semaphore schützen.
Ich denke es geht schief wenn der Hauptthread das ListCtrl updated und
gleichzeitig der Thread auch auf das ListCtrl rumrutscht.

Die MFC (gerade auf einem PDA, Pocket PC2003??) ist nicht Threadsafe.

Gruß
Stefan

PS: Ich weiß Mikkisoft sagt zwar sie sind Threadsafe aber das fällt
mehr unter Wunsch als unter Wirklichkeit.

du mußt jeden Zugriff auf m_pMyList mit einer Semaphore
schützen.

Also nur wenn ich irgendwelche Methode über m_pMyList Aufrufe?

CSingleLock sLock(&(theApp.m\_mutex));

// Anweisungen ...

sLock.Lock();
m\_pMyList-\>MyMethodXY();
sLock.Unlock();

// Anweisungen ...

sLock.Lock();
m\_pMyList-\>SetItemText(nItem, 0, strItem);
sLock.Unlock();

Oder auch in den Methoden der ListCtrl selber?
zB. In OnCustomDraw, wenn darin Methoden der ListCtrl aufgerufen werden.
Beispiel: Wenn ein bestimmter Text als Item eingetragen ist, so soll er rot markiert werden. Hierzu muss ich ja mittels GetItemText den Text holen.

Danke für eine Antwort
Gruß,
Tom

Oder auch in den Methoden der ListCtrl selber?

Das ist schlecht, da man mit sowas schnell zu einem Deadlock kommen
kann. Du mußt dann recht genau überlegen wer, was, wann aufrufen kann.

zB. In OnCustomDraw, wenn darin Methoden der ListCtrl
aufgerufen werden.

Der Aufruf OnCustomDraw selbst sollte geschützt sein.

Beispiel: Wenn ein bestimmter Text als Item eingetragen ist,
so soll er rot markiert werden. Hierzu muss ich ja mittels
GetItemText den Text holen.

Es geht immer schief wenn zwei Threads gleichzeitg auf die gleichen
Daten zugreifen. Solange beide nur lesen „kann“ das funktionieren,
sobald ein Thread Daten verändert geht das in die Pampa.
Damit beide Thread gleichzeitig lesen können müssen die inneren
Funktionen reentrant sein, was bei der PocketPC MFC auch nicht
immer gegeben ist.

Eine einfache aber sichere Lösung ist mit dem Thread lediglich
Messages (PostMessage nicht SendMessage) an den Hauptthread zu
schicken und dieser ändert die Daten. In diesem Fall würde dann
Windows durch seine MessageQueue die Zugriffe serialisieren.

Gruß
Stefan