I need to make TcpClient event driven rather than polling for messages all the time, so I thought: I will create a thread that would wait for a message to come and fire an event once it does. Here is a general idea:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace ThreadsTesting
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
//imitate a remote client connecting
TcpClient remoteClient = new TcpClient();
remoteClient.Connect(IPAddress.Parse("127.0.0.1"), 80);
//start listening to messages
p.startMessageListener();
//send some fake messages from the remote client to our server
for (int i = 0; i < 5; i++)
{
remoteClient.GetStream().Write(new byte[] { 0x80 }, 0, 1);
Thread.Sleep(200);
}
//sleep for a while to make sure the cpu is not used
Console.WriteLine("Sleeping for 2sec");
Thread.Sleep(2000);
//attempt to stop the server
p.stopMessageListener();
Console.ReadKey();
}
private CancellationTokenSource cSource;
private Task listener;
private TcpListener server;
private TcpClient client;
public Program()
{
server = new TcpListener(IPAddress.Parse("127.0.0.1"), 80);
server.Start();
}
private void startMessageListener()
{
client = server.AcceptTcpClient();
//start listening to the messages
cSource = new CancellationTokenSource();
listener = Task.Factory.StartNew(() => listenToMessages(cSource.Token), cSource.Token);
}
private void stopMessageListener()
{
Console.Out.WriteLine("Close requested");
//send cancelation signal and wait for the thread to finish
cSource.Cancel();
listener.Wait();
Console.WriteLine("Closed");
}
private void listenToMessages(CancellationToken token)
{
NetworkStream stream = client.GetStream();
//check if cancelation requested
while (!token.IsCancellationRequested)
{
//wait for the data to arrive
while (!stream.DataAvailable)
{ }
//read the data (always 1 byte - the message will always be 1 byte)
byte[] bytes = new byte[1];
stream.Read(bytes, 0, 1);
Console.WriteLine("Got Data");
//fire the event
}
}
}
}
This for obvious reasons doesn't work correctly:
while (!stream.DataAvailable) blocks the thread and uses always 25% CPU (on 4-core CPU), even if no data is there.
listener.Wait(); will wait for ever since the while loop doesn't pick up that cancel has been called.
My alternative solution would be using async calls within the listenToMessages method:
private async Task listenToMessages(CancellationToken token)
{
NetworkStream stream = client.GetStream();
//check if cancelation requested
while (!token.IsCancellationRequested)
{
//read the data
byte[] bytes = new byte[1];
await stream.ReadAsync(bytes, 0, 1, token);
Console.WriteLine("Got Data");
//fire the event
}
}
This works exactly as I expected:
The CPU is not blocked if there are no messages in the queue, but we are still waiting for them
Cancelation request is picked up correctly and thread finished as expected
I wanted to go further though. Since listenToMessages now returns a Task itself, I thought there is no need of starting a task that would execute that method. Here is what I did:
private void startMessageListener()
{
client = server.AcceptTcpClient();
//start listening to the messages
cSource = new CancellationTokenSource();
listener = listenToMessages(cSource.Token);
}
This doesn't work as I have expected in the sence that when Cancel() is called, the ReadAsync() method doesn't seem to pick up the cancelation message from the token, and the thread doesn't stop, instead it is stuck on the ReadAsync() line.
Any idea why is this happening? I would think the ReadAsync will still pick up the token, as it did before...
Thanks for all your time and help.
-- EDIT --
Ok so after more in depth evaluation my solution no.2 doesn't really work as expected:
the thread itself ends to the caller and so the caller can continue. However, the thread is not "dead", so if we send some data it will execute once more!
Here is an example:
//send some fake messages from the remote client to our server
for (int i = 0; i < 5; i++)
{
remoteClient.GetStream().Write(new byte[] { 0x80 }, 0, 1);
Thread.Sleep(200);
}
Console.WriteLine("Sleeping for 2sec");
Thread.Sleep(2000);
//attempt to stop the server
p.stopListeners();
//check what will happen if we try to write now
remoteClient.GetStream().Write(new byte[] { 0x80 }, 0, 1);
Thread.Sleep(200);
Console.ReadKey();
This will output the message "Got Data" even though in theory we stopped! I will investigate further and report on my findings.
With modern libraries, any time you type new Thread, you've already got legacy code.
The core solution for your situation is asynchronous socket methods. There are a few ways to approach your API design, though: Rx, TPL Dataflow, and plain TAP come to mind. If you truly want events then EAP is an option.
I have a library of EAP sockets here. It does require a synchronizing context, so you'd have to use something like ActionDispatcher (included in the same library) if you need to use it from a Console application (you don't need this if you're using it from WinForms/WPF).
ReadAsync doesn't seem to support cancellation on a NetworkStream - have a look at the answers in this thread:
NetworkStream.ReadAsync with a cancellation token never cancels
Related
I am writing a TCP server using Async / Await that needs to send a list of messages to connected clients, based on what it receives from each client. Between each message sent to the client, I need to:
wait for an acknowledgement/response then send the next messages
resend the command if no acknowledgement after 5 seconds
To do this, I am setting a ResponseReceived property on my ConnClient class when the expected response comes in. Then, in the ConnClient.SendListAsync routine, I am checking to see if the property has been changed after sending each command. However, incoming responses are not read until the SendListAsync sends all messages, as can be seen in my debug statements below:
Sending Initial Message.
Received response, generate list of 3 initial commands and send them.
SendListAsync 5 second timeout w/o response.
SendListAsync 5 second timeout w/o response.
SendListAsync 5 second timeout w/o response.
Received response.
Received response.
Received response.
Question: How can I properly prevent ConnClient.SendListAsync from blocking incoming reads?
public class Svr
{
TcpListener listener;
public async Task Listen(IPAddress iP, int port)
{
listener = new TcpListener(iP, port);
listener.Start();
while (true)
{
TcpClient client = await listener.AcceptTcpClientAsync();
ConnClient cc = new ConnClient(client);
await Receive(ConnClient);
}
}
async Task Receive(ConnClient cc)
{
var headerSize = sizeof(short);
byte[] buffer = new byte[4000];
//Send initial msg
await cc.socket.GetStream().WriteAsync(Strings.InitialMsg, 0, Strings.InitialMsg.Length);
while (true)
{
buffer = new byte[headerSize];
if (!await ReadToBuffer(cc.socket.GetStream(), buffer, headerSize))
return;
var length = BitConverter.ToUInt16(new byte[2] { buffer[1], buffer[0] }, 0 );
buffer = new byte[length];
if (!await ReadToBuffer(cc.socket.GetStream(), buffer, length))
return;
await DoSomethingBasedOnReceived(messageBuffer, cc);
}
}
async Task<Boolean> ReadToBuffer(NetworkStream stream, byte[] buffer, int bytesToRead)
{
int offset = 0;
while (offset < bytesToRead)
{
var length = await stream.ReadAsync(buffer, offset, bytesToRead - offset);
if (length == 0)
return false;
offset += length;
}
return true;
}
public async Task DoSomethingBasedOnReceived(byte[] messageBuffer, ConnClient cc)
{
await SomeLogicToSetTheRRFlagIfMessageApplicable(messageBuffer, cc);
List<byte[]> ListOfMessagesToSend = SomeLogicToDetermineListOfMessages(messageBuffer);
await cc.SendListAsync(ListOfMessagesToSend);
}
}
ConnClient Class, representing an individual connected client.
public class ConnClient
{
public TcpClient socket { get; set; }
public Boolean ResponseReceived { get; set; }
public ConnClient (TcpClient cc)
{socket = cc}
public async Task SendListAsync(List<byte[]> messageList)
{
foreach (byte[] msg in messageList)
{
this.ResponseReceived = false;
await stream.WriteAsync(msg, 0, msg.Length);
int waitedSoFar = 0;
while (waitedSoFar < 5000)
{
if (this.ResponseReceived == true)
{
break;
}
waitedSoFar += 100;
await Task.Delay(100);
}
}
}
}
Your first problem is you will not be able to accept new clients.
while (true)
{
// accept the next connection
TcpClient client = await listener.AcceptTcpClientAsync();
// receive and send list
ConnClient cc = new ConnClient(client);
await Receive(ConnClient);
// the loop cannot continue to receive the next connection
// until you have done with your receive
}
You will need to execute Receive independently so you can wait for the next connection, you can either call it without an await (which will run as an async void), or offload it to a new task .
Remove the await
Receive(ConnClient);
Offloading
Task.Run(() => Receive(ConnClient));
Your second problem is your client is held up while sending and will not be able to receive. Once again you will to either offload, or run without the await.
As #PeterDuniho mentions
Given that the OP is already using async/await, and given that
Receive() is already async, there's no reason to use Task.Run(). It's
fire-and-forget either way (unless they change their code to store the
returned task), so they might as well just fire-and-forget the call to
Receive() as wrap it in a call to Task.Run().
Note : Creating a scalable client/server socket solution is not trivial, and i am not attempting to show this. However, it will solve your current problem.
Either way, be very mindful of errors. Since both the proposed solutions will run unobserved, exceptions will need to be handled
I'm used to Begin/end APM pattern and i would like to update my socket server to .Net 4.5/async/await. I wrote an sample code from internet sources and it's not working.
I would like to have all the connected clients separated to own classes after they been accepted to connect (not yet implemented..). The loop which accepts all incoming connections is running at own thread.
Basically Main.cs is the place where i accept client, create new class (Client.cs/Session.cs) for connection and point that accepted client to that class. Well, that is what i'm planning to do and its not in the code and the main problem currently are my knowledge of how to handle this accepting sequence and why i cant connect more than one client at the time ? I hope you can point me to correct answer.
Thank you in advance.
Codes
Form1.cs
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Server
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Own thread for accepting connections
Main ConnectionLoop = new Main(10);
Thread thread = new Thread(new ThreadStart(ConnectionLoop.PrepareThread));
thread.IsBackground = true;
thread.Start();
}
}
}
Main.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Server
{
public class Main
{
private int m_backLog = 0;
// constructor
public Main(int Backlog)
{
m_backLog = Backlog;
Console.WriteLine("Main class created, backlog: {0}", Backlog);
}
public void PrepareThread()
{
Console.WriteLine("Thread created");
StartAccepting(CancellationToken.None).Wait();
}
private async Task StartAccepting(CancellationToken token)
{
Console.WriteLine("Started listening..");
CancellationTokenSource cts = new CancellationTokenSource();
TcpListener listener = new TcpListener(IPAddress.Any, 6112);
listener.Start();
await AcceptClientsAsync(listener, cts.Token);
// Thread.Sleep(600000);
}
private async Task AcceptClientsAsync(TcpListener listener, CancellationToken token)
{
var clientCounter = 0;
while (!token.IsCancellationRequested)
{
TcpClient client = await listener.AcceptTcpClientAsync().ConfigureAwait(false);
clientCounter++;
Console.WriteLine("Client {0} accepted!", clientCounter);
await EchoAsync(client, clientCounter, token);
}
}
private async Task EchoAsync(TcpClient client, int clientCounter, CancellationToken token)
{
using (client)
{
var buf = new byte[4096]; // buffer for stream
var stream = client.GetStream(); // stream itself
while (!token.IsCancellationRequested)
{
// some conditions we don't know is client connected, lets have timeout
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(15));
var amountReadTask = stream.ReadAsync(buf, 0, buf.Length, token);
var completedTask = await Task.WhenAny(timeoutTask, amountReadTask).ConfigureAwait(false);
if (completedTask == timeoutTask)
{
var msg = Encoding.ASCII.GetBytes("Client timed out");
await stream.WriteAsync(msg, 0, msg.Length);
break;
}
var amountRead = amountReadTask.Result;
if (amountRead == 0) break; // end of stream
await stream.WriteAsync(buf, 0, amountRead, token).ConfigureAwait(false);
}
}
Console.WriteLine("Client {0} disconnected", clientCounter);
}
}
}
Async is for long running processes, and prevents unnecessary waiting on long running I/O bound processes. It DOESN'T provide any kind of concurrency whatsoever. It just frees up the CPU so it doesn't sit around waiting.
So you will need to utilize the rest of the TPL (Task Parallel Library) to provide the concurrency you need to allow simultaneous clients. Likely this means spinning off a Task for the client once the connection occurs, and using that Task to manage the client.
Async can compliment that by making sure each client doesn't block a full thread, but by itself async only helps you not block, it doesn't provide concurrency.
First off, I would like to strongly recommend reading all of the info over at MSDN about the TPL. It's alot, but it is good reading and will help immensely.
https://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx
As for a more concrete example, I can try.
In your loop where you accept clients, you will want to gain parallelism as soon as you have a connected client. This will enable your run loop to go back to accepting clients, and let the client still interact. So for example:
private async Task AcceptClientsAsync(TcpListener listener, CancellationToken token)
{
var clientCounter = 0;
while (!token.IsCancellationRequested)
{
TcpClient client = await listener.AcceptTcpClientAsync().ConfigureAwait(false);
clientCounter++;
Console.WriteLine("Client {0} accepted!", clientCounter);
Task.Run(async () => await EchoAsync(client, clientCounter, token), token);
}
}
Note this is psuedo code. I didn't try compiling it. But the concept is solid.
If you have large amounts of clients you will need to be more specific than just using Task.Run, but for a sample it works fine. It will utilize Thread pool threads for the parallelism. Which works fine for at least 100, but can decrease in performance after that.
An async function returns a task that is completed when that function completes.
In your AcceptClientsAsync function, you're awaiting the EchoAsync function. This means that AcceptTcpClientAsync will not be called again until after EchoAsync completes (that is, after the cancellation token is signalled).
For an asynchronous socket server, you should have one task that only accepts in a loop, and for each connection, you should have a "processing" task. These have to be independent - you can't await the processing task from the accepting task.
Update: Adding example, as per request:
private async Task AcceptClientsAsync(TcpListener listener, CancellationToken token)
{
var clientCounter = 0;
while (!token.IsCancellationRequested)
{
TcpClient client = await listener.AcceptTcpClientAsync().ConfigureAwait(false);
clientCounter++;
Console.WriteLine("Client {0} accepted!", clientCounter);
var echoTask = EchoAsync(client, clientCounter, token);
// TODO: save the echoTask in some kind of per-client data structure.
}
}
I am trying to ping a host with ping.SendAsync.
Right now i use visual studio 2010 and .net 4
I would like to ping the specified host until i force stop ping.SendAsync.
The desired result is like when i use the command
ping -t host
Right now I learn using the example here:
https://msdn.microsoft.com/en-us/library/ms144962%28v=vs.110%29.aspx
But I can't find how to do it.
using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
public static void AsyncComplexLocalPing ()
{
// Get an object that will block the main thread.
AutoResetEvent waiter = new AutoResetEvent (false);
// Ping's the local machine.
Ping pingSender = new Ping ();
// When the PingCompleted event is raised,
// the PingCompletedCallback method is called.
pingSender.PingCompleted += new PingCompletedEventHandler (PingCompletedCallback);
IPAddress address = IPAddress.Loopback;
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes (data);
// Wait 10 seconds for a reply.
int timeout = 10000;
// Set options for transmission:
// The data can go through 64 gateways or routers
// before it is destroyed, and the data packet
// cannot be fragmented.
PingOptions options = new PingOptions (64, true);
// Send the ping asynchronously.
// Use the waiter as the user token.
// When the callback completes, it can wake up this thread.
pingSender.SendAsync (address, timeout, buffer, options, waiter);
// Prevent this example application from ending.
// A real application should do something useful
// when possible.
waiter.WaitOne ();
Console.WriteLine ("Ping example completed.");
}
Could anyone give me a good tip on how to make the ping.sendasynk keep sending the packets untill i kill the program/or i press a key/or a timer terminates it? Should i just loop the commands? Thank you in advance.
If you don't need to worry about running the query asynchronously, you can consider using .ContinueWith() and .Wait() and putting the ping method in a loop. This will make the asynchronous method behave like a synchronous call. Pseudocode:
while(looping)
{
pingSender.SendAsync(params).ContinueWith((pingTask) =>
{
var responseMessage = pingTask.Result;
if (goodResponse)
{
doSomething
}
}).Wait(timeout);
}
I want to create Socket message sending via TAP via async/await.
After reading this answer and this one - I decided to create a fully working sample :
So what have I tried :
I took the TAP extenstion methods from here (all ok) : and I test it in console cmd :
Reciever Code
public static class SocketExtensions
{
public static Task<int> ReceiveTaskAsync(this Socket socket, byte[] buffer, int offset, int count)
{
return Task.Factory.FromAsync<int>(
socket.BeginReceive(buffer, offset, count, SocketFlags.None, null, socket),
socket.EndReceive);
}
public static async Task<byte[]> ReceiveExactTaskAsync(this Socket socket, int len)
{
byte[] buf = new byte[len];
int totalRead = 0;
do{
int read = await ReceiveTaskAsync(socket, buf, totalRead, buf.Length - totalRead);
if (read <= 0) throw new SocketException();
totalRead += read;
}while (totalRead != buf.Length);
return buf;
}
public static Task ConnectTaskAsync(this Socket socket, string host, int port)
{
return Task.Factory.FromAsync(
socket.BeginConnect(host, port, null, null),
socket.EndConnect);
}
public static Task SendTaskAsync(this Socket socket, byte[] buffer)
{
return Task.Factory.FromAsync<int>(
socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, null, socket),
socket.EndSend);
}
}
static void Main()
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.ConnectTaskAsync("127.0.0.1", 443);
var buf1 = s.ReceiveExactTaskAsync(100); //read exactly 100 bytes
Console.Write(Encoding.UTF8.GetString(buf1.Result));
var buf2 = s.ReceiveExactTaskAsync(100); //read exactly 100 bytes
Console.Write(Encoding.UTF8.GetString(buf2.Result));
Console.ReadLine();
}
Sender Code :
// use same extension method class like above ....^
void Main()
{
Socket s = new Socket(SocketType.Stream , ProtocolType.Tcp);
s.ConnectTaskAsync( "127.0.0.1" , 443);
s.SendTaskAsync(Encoding.UTF8.GetBytes("hello"));
s.Close();
Console.ReadLine();
}
notice I removed the async from main since im testing it in console.
Question ,
According to link above , the code should work
However I'm getting no exception and it's just hangs on that line :
Console.Write(Encoding.UTF8.GetString(buf1.Result));
(First I run receiver , then I run sender)
What am I missing?
the problem comes from the "notice I removed the async from main since im testing it in console.".
You need to wait for the operation to complete before doing the next step. The code you used as an example pauses at each await for the operation to complete, your code just goes straight through.
You may be able to fix this by putting a .Wait() after each operation that would have had a await or by running this function inside a threadpool thread via Task.Run(, however I think it is better to know when you should use async and when you should not.
Async should be used when you have other work you could have the thread be doing, very commonly that "other work" will be things like processing UI messages on a WinForms project or accepting new connections on a ASP.NET site. In a console application there is no other work your program could be doing while it waits, so in that situation it would be more appropriate to use the synchronous version of the functions instead.
P.S. You made the comment after I posted "that's why I remove the async awaits and used Task.result", just so you know never ever1 combine code that uses await and code that blocks the synchronization contest (by using things like Task.Result or Task.Wait(), you will likely cause your code to deadlock and stop functioning!
It is not a issue for your current example because console applications do not have a synchronization context, but if you copied and pasted this code to something that did you could easily lock up your program.
1: Ok, you could combine await and blocking code but there are rules you need to follow, but if you know enough to dispute my what I am saying you know enough to safely do it. If you don't know how to safely do it just avoid doing it
since you do not wait for the threads to do their work and then call s.Close() the socket will be closed before any traffic is sent out.
You would have to either remove the s.Close() call or wait until the calls are complete, for instance via
Task connect = s.ConnectTaskAsync( "127.0.0.1" , 443);
connect.Wait(); // you have to connect before trying to send
Task sendData = s.SendTaskAsync(Encoding.UTF8.GetBytes("hello"));
sendData.Wait(); // wait for the data to be sent before calling s.Close()
s.Close();
or you could box it in a method and Wait for that method to complete. The end result is to not call Close before completing the previous calls.
void Main()
{
Socket s = new Socket(SocketType.Stream , ProtocolType.Tcp);
Task worker = DoWorkAsync(s);
worker.Wait();
s.Close();
Console.ReadLine();
}
private async Task DoWorkAsync(Socket s){
await s.ConnectTaskAsync( "127.0.0.1" , 443);
await s.SendTaskAsync(Encoding.UTF8.GetBytes("hello"));
}
So, I'm kind of new to multithreading and socket programming, especially in C#.
Anyways, I'm trying to create a program that creates each new accepted TcpClient as a new thread.
This is what I made:
public static void Listen()
{
try
{
listener = new TcpListener(IPAddress.Any, port);
listener.Start();
while (true)
{
t = new Thread((client = listener.AcceptTcpClient));
}
}
catch { Listen(); }
}
I also have already declared listener as a TcpListener, t as a Thread, and client as a TcpClient.
The code is fine, except for where I create the thread, it gives me an error.
My ultimate goal is to create a new thread for each accepted connection, then be able to send data to a specific connection.
So, how do I create each connection/client in a new thread? How do I reference a certain thread/connection from another method called Send (to send the data over a stream to a specific thread/connection only)?
Since you mention that you are new to threading and sockets I will recommend a change in approach. Creating a new thread per incoming connection will not scale well. 1000 users results in 1000 threads and your server will spend most of it's time context switching. Instead you should consider using async I/O methods (e.g. TcpListener.BeginAcceptTcpClient). The callback that you provide to this method will be invoked on a .NET thread pool thread only when it is required to do something. Just be sure to synchronize access to instance variables (e.g. via a lock statement) since if two clients connect simultaneously the callbacks may run in parallel (which is, of course, the goal). Best of luck.
Here's my start method for a socket server sample I had. Note new thread takes new ThreadStart as an argument. I can send more of the sample if needed.
It uses ThreadPool.QueueUserWorkitem instead of using a thread per request. Look at the listener.
public void Start()
{
m_protocol = LoadProtocolPlugIn();
// Create a TcpListener to accept client connection requests
TcpListener tcpListener = new TcpListener(m_address, m_port);
tcpListener.Start();
//
// Create a protocol listener per thread
//
for (int i = 0; i < m_listeners; i++)
{
ProtocolListener listener = new ProtocolListener(tcpListener, m_protocol);
Thread thread = new Thread(new ThreadStart(listener.Start));
thread.Start();
Console.WriteLine("Listening on thread: {0}", thread.Name);
}
m_state = ServerState.Started;
}
and here's the protocol listener:
class ProtocolListener
{
TcpListener m_listener;
IProtocol m_protocol = null;
TcpClient m_client = null;
internal ProtocolListener(TcpListener listener, IProtocol protocol)
{
m_listener = listener;
m_protocol = protocol;
}
internal void Start()
{
//
// Block waiting for socket connection and then process. Repeat in endless loop.
//
while (true)
{
try
{
m_client = m_listener.AcceptTcpClient();
ThreadPool.QueueUserWorkItem (new WaitCallback(ProcessClientProtocol), m_protocol);
}
catch (SocketException se)
{
// TODO: replace with logging and event log
Console.WriteLine("Exception = " + se.Message);
}
}
}
private void ProcessClientProtocol (object protocol)
{
Debug.Assert(m_client != null);
Debug.Assert(protocol != null);
((IProtocol)protocol).Client = m_client;
((IProtocol)protocol).ProcessClient();
}
}
This is not a very good way to do things. You should look at the either the BeginXXX/EndXXX pattern or the Async pattern for sockets.
http://msdn.microsoft.com/en-us/library/bbx2eya8.aspx
The Thread constructor takes a delegate, while you are trying to give it an object.
When you create a thread, you need to provide a method to be executed in that thread. For example:
private void HandleClient(TcpClient client)
{
// ...
}
However, it is usually a bad idea to create your own threads. You should use ThreadPool or Task Parallel Library, if you are using .NET 4:
ThreadPool.QueueUserWorkItem(() => HandleClient(acceptedClient));
or
Task.Factory.StartNew(() => HandleClient(acceptedClient));