Skip to main content
gamedev.net
🔒 Locked

C# locking threads

Started by Mr Cucumber Nov 19, 2003 at 10:52 AM 3 replies 1.2k views
Original Post
Mr Cucumber
Mr Cucumber
I have created some network code that apparently locks itself. The program starts a thread that goes into a loop that waits for a message. When I want the program to exit I call t.Abort on that thread. The thread I make the Abort call in has a t.Join that waits for the loop thread to shutdown. This never happens. The thread goes to state AbortRequested but never continues to Stopped. Heres a simple version of my program that works the same way and gets the same problem: The code for the server:
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Threading;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace NetServer
{
	class Server
	{
		private TcpClient client;
		private TcpListener listener;

		public Server()
		{
		}
		
		public void Start()
		{
			this.listener = new TcpListener(IPAddress.Any, 8000);
			listener.Start();
			Console.WriteLine("Before contact");
			this.client = listener.AcceptTcpClient();
			Console.WriteLine("Client connected");

			ThreadStart ts = new ThreadStart(this.GetData);
			Thread t = new Thread(ts);
			t.Start();

			Thread.Sleep(500);
			Console.WriteLine("Status: " + t.ThreadState.ToString());
			Thread.Sleep(500);
			Console.WriteLine("Status: " + t.ThreadState.ToString());
			Thread.Sleep(500);
			Console.WriteLine("Status: " + t.ThreadState.ToString()); //Printing out Running


			Thread.Sleep(10000);
			Console.WriteLine("Close thread soon");
			Thread.Sleep(2000);
			Console.WriteLine("Close it!");
			t.Abort();
			Thread.Sleep(500);
			Console.WriteLine("Status: " + t.ThreadState.ToString());
			Thread.Sleep(500);
			Console.WriteLine("Status: " + t.ThreadState.ToString());
			Thread.Sleep(500);
			Console.WriteLine("Status: " + t.ThreadState.ToString()); //Printing out AbortRequested

			t.Join(); //This never happens

			Console.WriteLine("Joined");
		}
		
		public void GetData()
		{
			try
			{
				NetworkStream ns = client.GetStream();
				StreamReader sr = new StreamReader(ns);

				for(;;)
				{
					sr.ReadLine();
					Console.WriteLine("Received message");
				}
			}
			catch(ThreadAbortException)
			{
				Console.WriteLine("Caught ThreadAbortException");
			}
			
		}
		
		[STAThread]
		static void Main(string[] args)
		{
			Server ser = new Server();
			ser.Start();
			Console.ReadLine();
		}
	}
}
And heres the code for the client:
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Threading;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace NetClient
{
	class Client
	{
		private TcpClient client;

		public Client()
		{
		}
		
		public void Start()
		{
			client = new TcpClient();
			client.Connect("localhost", 8000);
			Console.WriteLine("Got contact");
			ThreadStart ts = new ThreadStart(this.GetData);
			Thread t = new Thread(ts);
			t.Start();

			Thread.Sleep(500);
			Console.WriteLine("Status: " + t.ThreadState.ToString());
			Thread.Sleep(500);
			Console.WriteLine("Status: " + t.ThreadState.ToString());
			Thread.Sleep(500);
			Console.WriteLine("Status: " + t.ThreadState.ToString()); //Printing out running


			Thread.Sleep(5000);
			Console.WriteLine("Close thread soon");
			Thread.Sleep(2000);
			Console.WriteLine("Close it!");
			t.Abort();
			Thread.Sleep(500);
			Console.WriteLine("Status: " + t.ThreadState.ToString());
			Thread.Sleep(500);
			Console.WriteLine("Status: " + t.ThreadState.ToString());
			Thread.Sleep(500);
			Console.WriteLine("Status: " + t.ThreadState.ToString()); //Printing out AbortRequested

			t.Join(); //This never happens

			Console.WriteLine("Joined");
		}
		
		public void GetData()
		{
			try
			{
				NetworkStream ns = client.GetStream();
				StreamReader sr = new StreamReader(ns);

				for(;;)
				{
					sr.ReadLine();
					Console.WriteLine("Mottog meddelande");
				}
			}
			catch(ThreadAbortException)
			{
				Console.WriteLine("Mottog ThreadAbortException och avslutar");
			}

			//Läs strängen

			
		}
		[STAThread]
		static void Main(string[] args)
		{
			Client c = new Client();
			c.Start();
			Console.ReadLine();
		}
	}
}
Is there anyone who spots the problem? [edited by - Mr Cucumber on November 19, 2003 11:55:51 AM]
noparity
noparity
The TcpClient class you''re using works in synchronous mode only, so whenever you read/write from this stream your calls will block until they complete. The call to ReadLine() reads from the stream untill it reaches a line feel (''\n'') character. Since the stream you''re reading from contains no line feed character (in fact, it contains no characters), the call to ReadLine() never returns. One solution is to only attempt to read from the stream if there''s data in it:

if (ns.DataAvailable)
{
sr.ReadLine();
Console.WriteLine("Received message");
}

The other solution is to use asyncronous sockets so your read/write operations don''t block.
Mr Cucumber
Mr Cucumber
I used a sr.Peek before to search for data, but appently that didnt work. No messages were ever received. Anyway I managed to find un ugly solution to the problem which involved making the ReadLine throw an exception that I could catch.
Maybe ns.DataAvailable works better.
noparity
noparity
sr.Peek() will also block until there is data in the stream to peek at.
daerid
daerid
What you want is the Socket class, and the BeginReceive()/EndReceive() methods (which perform Asynch I/O on the Socket)
daerid@gmail.com

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.