C# Thread Probleme mit Variablen

Wurschtl

Grünschnabel
Hallo, bin noch etwas neu in dieser Materie und hoffe auf eure Hilfe.
Programmiere gerade ein kleines Program was 2 separate Threads enthält.
Einer für die Kommunikation und ein zweiter für die allgemeine Abarbeitung.
Ich kann beide Threads starten und sauber beenden.
Im Thread für die Kommunikation wird eine Variable abgefragt. Wenn Sie "true" ist, soll er einfach einen String senden und die Variable wieder auf "false" setzen.
Der zweite Thread soll nach ablauf einer Zeit die diese auf "true" setzen und den Kommunikationsthread veranllasen zu senden.
Leider funktioniert das nicht so wie es soll. Was mach ich falsch?

Hier der Code:

Code:
"Der Timerthread"
protected void TimerLoop() 
{
	while( !_TimerStopRequest )
	{			
		if(main_serial_rx_tx_thd != null)
		{
			lock(lockvar)
			{
				main_serial_rx_tx_thd.SerialTransmitRequest = true;
			}
		}			
		 Thread.Sleep(500);
	}
}





"Funktion zur Veränderung der Variable"
public bool SerialTransmitRequest
{
	set { _Start_Serial_Transfer = value; }
}


"Kommunikationsthread"
protected void SerialLoop() 
{
	while( !_SerialStopRequest )
	{
		lock(lockvar)
		{
			if(_Start_Serial_Transfer)
			{
				serialPort1.Write("Hallo\r");
				_Start_Serial_Transfer = false;
			}
			Thread.Sleep(0);
		}				
	}
	serialPort1.Close();
}
 
Hallo,

beschreibe doch mal die Fehlfunktion genauer. Der Code scheint soweit ok zu sein.

Das Einzige was ich gerade sehe ist, dass der Zeitabstand zwischen den Sendungen ziemlich zufällig sein kann (je nachdem, wieviel "Thread.Sleep(500);" schon so abgearbeitet hat). Ist das beabsichtigt? Ansonsten würde ich da doch lieber einen Timer verwenden. Dieser wird nach dem Senden gestartet und im Timer-Event wieder gestoppt. So hast du ein konstantes Intervall zwischen den einzelnen Sendungen (Falls das so gewünscht ist).

Gruß
MCoder
 
Hallo MCoder,
erstaml danke für Deine Antwort.
Das Problem ist, das "SerialTransmitRequest" aufgerufen wird, der Status der boolschen VAriable auf true gesetzt wird (im Debuggmode sieht man auch die Variable auf true), wenn jedoch der Thread an der Abfrage ist, wird immer false gelesen. Es ist fast so als ob die Variable niem
Beide Thread laufen in Ihren unterschiedlichen Klassen, können jedoch sich irgendwie nicht gegenseitig beeinflussen.
Bei einem Test habe ich über ein ButtonClickEvent die Funtion "SerialTransmitRequest" genauso aufgerufen. Damit hatte es Funktioniert.
 
Wie und wo wird denn das Objekt "main_serial_rx_tx_thd" erstellt bzw. übergeben? Ich nehme mal an, die Methode "SerialLoop" gehört zu der Klasse, von der obiges Objekt erstellt wurde, das dann an die andere Klasse übergeben wird?

Gruß
MCoder
 
Die Timerloop arbeitet in einer eigenen Klasse und die Serialloop auch in Ihrer eigenen Klasse. Zur Veränderung des boolschen Status gibt es die Funktion SerialTransmitRequest die in der Klasse des Serialloop sich befindet.
 
Zeige doch mal die Codestellen, an denen "main_serial_rx_tx_thd" erzeugt und an die TimerLoop-Klasse übergeben wird.

Gruß
MCoder
 
Sow jetzt poste ich mal beide Files:

Hier der SerialThread:

Code:
/*
 * Erstellt mit SharpDevelop.
 * Benutzer: Nico
 * Datum: 26.02.2009
 * Zeit: 14:12
 * 
 * Sie können diese Vorlage unter Extras > Optionen > Codeerstellung > Standardheader ändern.
 */
using System;
using System.IO.Ports;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Windows.Forms;
using System.Threading;

namespace Bootloader
{
	public class SerialClassThread
	{
		public System.IO.Ports.SerialPort serialPort1;
		public Thread Serial_Thread;
				
		private string _Serial_tx_send_string;
		private bool _Serial_Rx_Buffer_Ready = false;
		private bool _SerialStopRequest = true;
		private bool _SerialTranmitRequest = false;
		
		public bool StopRequest
		{
			set { _SerialStopRequest = value; }
		}
		public bool TransmitRequest
		{
			set { _SerialTranmitRequest = value; }
		}
		public string SerialStringRequest 
		{
			set { _Serial_tx_send_string = value; }
		}

		public void StartThread(string to_open_comport,int to_open_baudrate) 
		{
			if ( Serial_Thread == null || ( Serial_Thread != null && !Serial_Thread.IsAlive ) ) {
				serialPort1 = new SerialPort(to_open_comport, to_open_baudrate, Parity.None, 8, StopBits.One);
				serialPort1.Open();
				_SerialStopRequest = false;	
				Serial_Thread = new Thread( new ThreadStart(SerialLoop) );
				Serial_Thread.Start();
				while (!Serial_Thread.IsAlive);
			}
		}
		protected void SerialLoop() 
		{
			while( !_SerialStopRequest )
			{
                               if( _SerialTranmitRequest)
                               {
				         serialPort1.Write(_Serial_tx_send_string);
                                          _SerialTranmitRequest = false;
                               }
			}
			serialPort1.Close();
			SystemTimer.Stop();
		}
	}	
}


und hier jetzt der Timerthread:

Code:
using System;
using System.Threading;
using System.Security.Cryptography;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.IO.Ports;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Windows;

namespace Bootloader
{
	public class TimerClassThread
	{

		public SerialClassThread main_serial_rx_tx_thd = new SerialClassThread();
		public Thread Timer_Thread;
		protected volatile bool _TimerStopRequest = true;
				
		public bool TimerThreadStopRequest 
		{
			set { _TimerStopRequest = value; }
		}
		public void StartThread() 
		{
			if ( Timer_Thread == null || ( Timer_Thread != null && !Timer_Thread.IsAlive ) ) 
			{
				_TimerStopRequest = false;
				Timer_Thread = new Thread( new ThreadStart(TimerLoop) );
				Timer_Thread.Start();
				while (!Timer_Thread.IsAlive);
			}
		}
		
			
	        private static Object lockvar = ""; // Lock-Variable
		protected void TimerLoop() 
		{
			while( !_TimerStopRequest )
			{
				if(main_serial_rx_tx_thd != null)
				{
					lock(lockvar)
					{
						main_serial_rx_tx_thd.SerialStringRequest = "Hallo\r";
						main_serial_rx_tx_thd.SerialTransmitRequest = true;
					}
				}
				else
				{
					if(main_serial_rx_tx_thd == null)
					{
						main_serial_rx_tx_thd.StartThread("COM6",9600);
					}	
				}
		       	Thread.Sleep(500);
			}
			MessageBox.Show("Timer Thread Closed", "Thread Closed",MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
		}
	}
}

ich wäre Dir echt dankbar wenn Du mir helfen könntest.
 
Hallo,

du erzeugst in "TimerClassThread" ein neues Objekt der Klasse "SerialClassThread", was mit dem bereits laufenden nichts zu tun hat und daher klappt das auch nicht mit den Variablen. Du müsstest an das TimerClassThread-Objekt das Objekt von "SerialClassThread" übergeben:
C#:
// Änderungen an der TimerClassThread-Klasse

public class TimerClassThread
{
		public SerialClassThread _main_serial_rx_tx_thd = null;
        
        ...
        
		public void StartThread(SerialClassThread main_serial_rx_tx_thd) 
		{
            _main_serial_rx_tx_thd = main_serial_rx_tx_thd;
            
            ...
		}

        ...
}        

// Verwendung

private SerialClassThread serial_thread = new SerialClassThread();
private TimerClassThread  timer_thread  = new TimerClassThread();

...

serial_thread.StartThread( ... );
timer_thread.StartThread(serial_thread);
Gruß
MCoder
 
Zurück