<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Thread Sync problem]]></title><description><![CDATA[<p>Hallo Zusammen,</p>
<p>habe einen Thread, der ein Event setzen soll, wenn er was gemacht hat und an anderer Stelle soll ein Dialog etwa 1s auf das das Setzen des Events warten und dann weitermachen, oder nach Ablauf der Sekunde eine Meldung machen (falls der Event bis dahin nicht gesetzt wird).</p>
<pre><code class="language-cpp">CEvent evtParameter;
</code></pre>
<p>Setze evtParameter so:</p>
<pre><code class="language-cpp">MyDlg-&gt;evtParameter.SetEvent();
</code></pre>
<p>und warte an anderer Stelle (nicht im Thread) auf das Event</p>
<pre><code class="language-cpp">if (WaitForSingleObject(MyDlg-&gt;evtParameter,1000) == WAIT_TIMEOUT) AfxMessageBox(&quot;NO PARAMETER AVAILABLE!&quot;, MB_OK | MB_ICONSTOP);
</code></pre>
<p>Leider passiert aber folgendes:<br />
Der Thread läuft nur bis zu dem Befehl SetEvent() und wartet dann (!?!) und das WaitForSingleObject läuft immer in den Timeout. Nachdem der Timeout eingetreten ist, läuft der Thread ironischerweise weiter... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/topic/203613/thread-sync-problem</link><generator>RSS for Node</generator><lastBuildDate>Sun, 05 Apr 2026 11:01:15 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/203613.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 24 Jan 2008 13:07:05 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Thread Sync problem on Thu, 24 Jan 2008 13:07:05 GMT]]></title><description><![CDATA[<p>Hallo Zusammen,</p>
<p>habe einen Thread, der ein Event setzen soll, wenn er was gemacht hat und an anderer Stelle soll ein Dialog etwa 1s auf das das Setzen des Events warten und dann weitermachen, oder nach Ablauf der Sekunde eine Meldung machen (falls der Event bis dahin nicht gesetzt wird).</p>
<pre><code class="language-cpp">CEvent evtParameter;
</code></pre>
<p>Setze evtParameter so:</p>
<pre><code class="language-cpp">MyDlg-&gt;evtParameter.SetEvent();
</code></pre>
<p>und warte an anderer Stelle (nicht im Thread) auf das Event</p>
<pre><code class="language-cpp">if (WaitForSingleObject(MyDlg-&gt;evtParameter,1000) == WAIT_TIMEOUT) AfxMessageBox(&quot;NO PARAMETER AVAILABLE!&quot;, MB_OK | MB_ICONSTOP);
</code></pre>
<p>Leider passiert aber folgendes:<br />
Der Thread läuft nur bis zu dem Befehl SetEvent() und wartet dann (!?!) und das WaitForSingleObject läuft immer in den Timeout. Nachdem der Timeout eingetreten ist, läuft der Thread ironischerweise weiter... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1442768</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1442768</guid><dc:creator><![CDATA[Rainer 2.0]]></dc:creator><pubDate>Thu, 24 Jan 2008 13:07:05 GMT</pubDate></item><item><title><![CDATA[Reply to Thread Sync problem on Thu, 24 Jan 2008 13:18:37 GMT]]></title><description><![CDATA[<p>Wäre nett, wenn jemand einen Tip für mich hättte! Vielen Dank!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1442780</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1442780</guid><dc:creator><![CDATA[Rainer 2.0]]></dc:creator><pubDate>Thu, 24 Jan 2008 13:18:37 GMT</pubDate></item><item><title><![CDATA[Reply to Thread Sync problem on Thu, 24 Jan 2008 18:13:55 GMT]]></title><description><![CDATA[<p>Hat wirklich keiner 'ne Idee?!?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1443006</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1443006</guid><dc:creator><![CDATA[Rainer 2.0]]></dc:creator><pubDate>Thu, 24 Jan 2008 18:13:55 GMT</pubDate></item><item><title><![CDATA[Reply to Thread Sync problem on Thu, 24 Jan 2008 21:26:28 GMT]]></title><description><![CDATA[<p>Zeig mal mehr Code her. Bis jetzt sieht das nicht falsch aus. Wenn ich nicht grad was übersehen hab.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1443158</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1443158</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Thu, 24 Jan 2008 21:26:28 GMT</pubDate></item><item><title><![CDATA[Reply to Thread Sync problem on Thu, 24 Jan 2008 22:24:22 GMT]]></title><description><![CDATA[<p>Hi hustbaer,</p>
<p>vielen herzlichen Dank, daß sich Du dich erbarmst und Dich meines Problems annimmst...</p>
<p>so sieht die Methode aus, die auf das vent warten soll:</p>
<pre><code class="language-cpp">void CX303ParameterDlg::OnAnfordernMasterAll()
{
  int		i,j,error;

  BOOL				State;
  LWORD				lwError;
  COMSTAT			ComStat;

  CString		cstrTmp;
  BYTE			byteTmp[32];
  unsigned int	crc;

  CSingleLock sLockSerial(&amp;(X303MonitorDlg-&gt;csSerial),TRUE);	// SingleLock Objekt konstruieren, da &quot;TRUE&quot; -&gt; Lock() wird aufgefufen!
																// bei Verlassen der Methode durch den Destructor des SingleLock-Objekts sLockSerial
																// von wird automatisch Unlock() aufgerufen!

		#ifdef DEBUG_LOG
   	      fprintf(FP_LOG,&quot;************ OnAnfordernMasterAll **************\n&quot;);
		#endif

  evtParameter.ResetEvent();

  crc = 0;
  crc = calc_crc(crc,0x02);
  crc = calc_crc(crc,0x02);
  crc = calc_crc(crc,0x7A);					
  crc = calc_crc(crc,0x03);
  crc = calc_crc(crc,0);
  crc = calc_crc(crc,0);

  byteTmp[0] = 0x02;
  byteTmp[1] = 0x02;
  byteTmp[2] = 0x7A;
  byteTmp[3] = 0x03;
  byteTmp[4] = (crc &amp; 0xFF);				// CRC-Low-Byte übertragen
  byteTmp[5] = (crc &gt;&gt; 8);					// CRC-High-Byte übertragen

  		#ifdef DEBUG_LOG
		  fprintf(FP_LOG,&quot;CRC: %d&quot;,crc);
          MEM_DUMP2(byteTmp,&quot;byteTmp: &quot;,16,6);
		  fprintf(FP_LOG,&quot;\n&quot;);
		#endif

  error = SeriellSend(hSerialPort,byteTmp,6);

  State = ClearCommError(hSerialPort,&amp;lwError,&amp;ComStat);

		#ifdef DEBUG_LOG
		  //lwError = GetLastError();
		  fprintf(FP_LOG,&quot;ERROR-R:  %04X -&gt; &quot;,lwError);;
		  if (lwError == 0) fprintf(FP_LOG,&quot;OK\n&quot;);
		  else if (lwError == CE_BREAK) fprintf(FP_LOG,&quot;CE_BREAK\n&quot;);
		  else if (lwError == CE_BREAK) fprintf(FP_LOG,&quot;CE_BREAK\n&quot;);
		  else if (lwError == CE_FRAME) fprintf(FP_LOG,&quot;CE_FRAME\n&quot;);
		  else if (lwError == CE_IOE) fprintf(FP_LOG,&quot;CE_IOE\n&quot;);
		  else if (lwError == CE_MODE) fprintf(FP_LOG,&quot;CE_MODE\n&quot;);
		  else if (lwError == CE_OVERRUN) fprintf(FP_LOG,&quot;CE_OVERRUN\n&quot;);
		  else if (lwError == CE_RXOVER) fprintf(FP_LOG,&quot;CE_RXOVER\n&quot;);
		  else if (lwError == CE_RXPARITY) fprintf(FP_LOG,&quot;CE_RXPARITY\n&quot;);
		  else if (lwError == CE_TXFULL) fprintf(FP_LOG,&quot;CE_TXFULL\n&quot;);
		#endif

	sLockSerial.Unlock();

				#ifdef DEBUG_LOG
				  fprintf(FP_LOG,&quot;**-P1-**\n&quot;);
					if (::WaitForSingleObject(evtParameter.m_hObject,0) == WAIT_OBJECT_0) fprintf(FP_LOG,&quot;EVENT GESETZT!\n&quot;);
					else fprintf(FP_LOG,&quot;EVENT NICHT GESETZT!\n&quot;);

				  fprintf(FP_LOG,&quot;\n&quot;);
				#endif

	// wartet auf deas Eintreffen derParameter TimeOut = 1s
	if (::WaitForSingleObject(evtParameter.m_hObject,0) == WAIT_TIMEOUT) AfxMessageBox(&quot;NO PARAMETER AVAILABLE!&quot;, MB_OK | MB_ICONSTOP);

    //for (i=0;i&lt;200000000;i++) j = i;
    //while (::WaitForSingleObject(evtParameter.m_hObject,0) == WAIT_TIMEOUT);

				#ifdef DEBUG_LOG
				  fprintf(FP_LOG,&quot;**-P2-**\n&quot;);
					if (::WaitForSingleObject(evtParameter.m_hObject,0) == WAIT_OBJECT_0) fprintf(FP_LOG,&quot;EVENT GESETZT!\n&quot;);
					else fprintf(FP_LOG,&quot;EVENT NICHT GESETZT!\n&quot;);

				  fprintf(FP_LOG,&quot;\n&quot;);
				#endif

	// Master-Paramter setzen
	for (i=0;i&lt;PARAMETER_ANZAHL;i++) 
	{
	  cstrTmp.Format(&quot;%d&quot;,shortParameterMaster[i]);
	  m_Parameter[i].SetWindowTextA(cstrTmp);
	}

}
</code></pre>
<p>und hier wird das Event gesetzt:</p>
<pre><code class="language-cpp">// Group (byteTmp) = 2 -&gt; Parameter (2 Byte Integer)
			// 0x41 - 0x4C -&gt; Status Master - alle Parameter
		    j = *(byteTmp + 1) &amp; 0xFF;								// Command-Byte sichern

	        cstrTmp.Format(&quot;%2d&quot;,10);								// Zahl der Parameter
	        Dlg-&gt;m_DatenListe.SetItemText(nItem, 2, cstrTmp);

	        cstrTmp.Format(&quot;%02X&quot;,*(byteTmp + 1));					// Command ausgeben
	        Dlg-&gt;m_DatenListe.SetItemText(nItem, 3, cstrTmp);	

			sLockSerial.Lock();
			error = SeriellReceive(hSerialPort,byteTmp,20);			// Parameter holen
			sLockSerial.Unlock();

		    #ifdef DEBUG_LOG
              MEM_DUMP2(byteTmp,&quot;byteTmp -P-: &quot;,16,2);
		      fprintf(FP_LOG,&quot;\n&quot;);
		    #endif

			for (i=0;i&lt;(PARAMETER_ANZAHL * 2);i++)
		    {
		      //sLockGUI.Lock();
		      *pbyteInput = *(byteTmp + i);
		      if ((pbyteInput - byteInput) &lt; MAX_INPUT) pbyteInput++;
		      //sLockGUI.Unlock();
			  crc = calc_crc(crc, *(byteTmp + i));					// Parameter High-Byte zur Checksumme hinzufügen
		    }

			cstrTmp.Format(&quot;ALLE PARAMETER              - MASTER&quot;);
		    Dlg-&gt;m_DatenListe.SetItemText(nItem, 6, cstrTmp);

				#ifdef DEBUG_LOG
				  MEM_DUMP2(byteTmp,&quot;byteTmp P-ALL: &quot;,20,20);
				  fprintf(FP_LOG,&quot;\n&quot;);
				#endif

			for(i=0;i&lt;PARAMETER_ANZAHL;i++) shortParameterMaster[i] = *(((unsigned short *) byteTmp) + i);

			evtParameter.SetEvent();

				#ifdef DEBUG_LOG
				  fprintf(FP_LOG,&quot;**--**\n&quot;);
					if (::WaitForSingleObject(evtParameter.m_hObject,0) == WAIT_OBJECT_0) fprintf(FP_LOG,&quot;EVENT GESETZT!\n&quot;);
					else fprintf(FP_LOG,&quot;EVENT NICHT GESETZT!\n&quot;);

				  fprintf(FP_LOG,&quot;\n&quot;);
				#endif

			// Master-Paramter setzen
			for (i=0;i&lt;PARAMETER_ANZAHL;i++) 
			{
			  cstrTmp.Format(&quot;%d&quot;,shortParameterMaster[i]);
			  Dlg2-&gt;m_Parameter[i].SetWindowTextA(cstrTmp);
			}

			cstrTmp2 = &quot;&quot;;
			for(i=0;i&lt;PARAMETER_ANZAHL;i++)
			{
			  cstrTmp.Format(&quot;% 5d &quot;,*(((unsigned short *) byteTmp) + i));
			  cstrTmp2 += cstrTmp;
			}
	        Dlg-&gt;m_DatenListe.SetItemText(nItem, 4, cstrTmp2);
</code></pre>
<p>der untere Teil zum Setzen des Events steck in einem Workerthread, der sonst auch gut funzt Zur Zeit verwende ich einen modeless-Dialog zum Anzeigen und editieren der Paramter - deshalb schreibt der Thread via Dlg2 direkt in den Dialog... Habe ich so gemacht, weil die Warterei nicht tut. Das Event wird aber tatsächlich gesetzt, was ich mit den Kontrollausgaben geprüft habe...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1443179</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1443179</guid><dc:creator><![CDATA[Rainer 2.0]]></dc:creator><pubDate>Thu, 24 Jan 2008 22:24:22 GMT</pubDate></item><item><title><![CDATA[Reply to Thread Sync problem on Fri, 25 Jan 2008 00:54:34 GMT]]></title><description><![CDATA[<blockquote>
<pre><code class="language-cpp">CEvent evtParameter;
</code></pre>
</blockquote>
<p>Guck mal da:</p>
<p>MSDN schrieb:</p>
<blockquote>
<p>CEvent(<br />
BOOL bInitiallyOwn = FALSE,<br />
<strong>BOOL bManualReset = FALSE,</strong><br />
LPCTSTR lpszName = NULL,<br />
LPSECURITY_ATTRIBUTES lpsaAttribute = NULL<br />
);</p>
</blockquote>
<p>Das bedeutet ein default konstruiertes CEvent ist ein &quot;auto reset&quot; Event. Und das wiederum bedeutet dass das erste WaitForSingleObject den Status auf &quot;non signaled&quot; zurücksetzt.</p>
<p>Vorausgesetzt du hast die Zeile oben nicht falsch abgetippt könnte das das Problem erklären. Auto reset Events sind grundsätzlich kein Problem (sondern oft sehr sehr nützlich), allerdings darf man genau solche Debug-Checks wie du welche in deinem Code hast damit nicht machen.</p>
<p>----</p>
<p>Das ganze sieht für mich aber sowieso nicht ganz sauber aus. Ich behaupte nicht dass es garantiert falsch ist, aber ich würde es niemals so machen.</p>
<p>Erstmal lass mich sagen dass die ganze Kommunikation mit dem Device in eine eigene Klasse wandern sollte. GUI und &quot;Serielles Protokoll ABC für Device XYZ&quot; sind zwei so grundlegend verschiedene Dinge, das sieht ein Blinder dass man das nicht mischen sollte <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>So. Zurück zu &quot;sieht unsauber aus&quot;. Ich würde z.B. nicht aus zwei verschiedenen Threads die Serielle Schnittstelle ansteuern um mit einem Gerät zu kommunizieren. Vor allem nicht so dass Thread A einen Request abschickt und Thread B dann auf die Antwort wartet. Nicht wenn es nicht notwändig ist (und das ist es oft nicht). Wenn du einen 2. Thread hast der die Antwort empfangen soll dann lass den auch den Request abschicken.</p>
<p>Um weiteres zu sagen müsste man wissen um was für eine Art Gerät es sich handelt, also was das kann, welches Protokoll es spricht, und natürlich auch was man mit dem Gerät machen will.</p>
<p>----</p>
<p>Wenn du noch nicht allzuviel Code geschrieben hast mach einfach ein neues Projekt, mach ein schönes Design, und implementiere die nötigen Funktionen dann indem du die entsprechenden Codestücke aus dem alten Projekt dorthin kopierst wo sie hingehören, und entsprechend anpasst.</p>
<p>Wenn das Projekt schon grösser ist ist hier mächtig Refactoring angesagt <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1443201</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1443201</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Fri, 25 Jan 2008 00:54:34 GMT</pubDate></item><item><title><![CDATA[Reply to Thread Sync problem on Fri, 25 Jan 2008 08:10:39 GMT]]></title><description><![CDATA[<p>Vielen Dank mal für die Durchsicht und die ausführliche ANtwort! Das Projekt liese sich schon noch mal neu aufsetzen, aber das kostet natürlich auch Zeit, die ich mir gern sparen würde.</p>
<p>hustbaer schrieb:</p>
<blockquote>
<p>Das ganze sieht für mich aber sowieso nicht ganz sauber aus.</p>
</blockquote>
<p>Aber wie soll ich das sonst machen: Ich habe einen Button im GUI, das einen Befehl an die Schnittstelle schickt und die Antwort soll von einem Thread im Hintergrund erledigt werden, der die Schnittstelle ständig pollt. Das GUI soll halt nicht einfrieren. Auf der anderen Seite sollen die Antwort im GUI dargestellt werden, also muß doch der Thread auf das GUI zugreifen, oder nicht?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1443241</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1443241</guid><dc:creator><![CDATA[Rainer 2.0]]></dc:creator><pubDate>Fri, 25 Jan 2008 08:10:39 GMT</pubDate></item><item><title><![CDATA[Reply to Thread Sync problem on Mon, 28 Jan 2008 14:43:22 GMT]]></title><description><![CDATA[<p>Mal als kleine Anregung:</p>
<p>Mach es doch so, dass der Thread die Daten in einer Datenstruktur bereitstellt. Das GUI kannst du dann per PostMessage davon unterichten, dass Daten da sind.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1445120</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1445120</guid><dc:creator><![CDATA[Burkhi]]></dc:creator><pubDate>Mon, 28 Jan 2008 14:43:22 GMT</pubDate></item><item><title><![CDATA[Reply to Thread Sync problem on Tue, 29 Jan 2008 01:15:17 GMT]]></title><description><![CDATA[<p>Sorry, hab übers Wochenende mit meiner Windows Installation gekämpft, und hab auf den Thread vergessen.</p>
<p>Allerdings ist es sowieso recht schwer für mich dir zu erklären wie ich das machen würde. Der Code den du da gepostet hast ist halt einfach ziemlich grauenhaft, und dass du nachfragst wie man es nun besser machen könnte lässt mich einfach vermuten dass du nicht so wahnsinnig viel Erfahrung hast.</p>
<p>Blöderweise ist aber die Aufgabe mit der du da kämpfst auch nicht gerade eine der einfachsten, schon garnicht wenn man dem Programm ein sauberes Design verpassen möchte.</p>
<p>Im Prinzip sollte man auf jeden Fall alles was mit der Kommunikation mit dem Device zu tun hat in eine eigene Klasse kapseln. Doof ist nur die Frage: wie soll das Interface so einer Kasse aussehen. Wenn asynchrone Operationen nötig sind wird das recht schnell recht unübersichtlich für jmd. der sowas noch nie gemacht hat.</p>
<p>Wenn du das ganze halbwegs einfach und übersichtlich halten willst ist das was Burkhi geschrieben hat schonmal keine schlechte Idee. Wenn du nun vom Dialog aus dem Thread irgendetwas mitteilen musst, kannst du auch Window Messages verwenden, oder auch Thread Messages (im Prinzip dasselbe wie eine Window Message, nur mit PostThreadMessage abgeschickt - so bräuchte der &quot;Device polling Thread&quot; kein Fenster).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1445422</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1445422</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 29 Jan 2008 01:15:17 GMT</pubDate></item></channel></rss>