I have been having playing with implementing some socket code to see if it fits my needs and so use the sample code #spender kindly added to this question.
If I run this on the main thread it works as expected but when I invoke it on a background thread it never gets awoken from its sleep when a client attempts to connect, my thread spawn is as below:
_Thread = new Thread(new ThreadStart(StartListening));
_Thread.Name = "ThreadForSocket";
_Thread.IsBackground = true;
_Thread.Start();
private void StartListening()
{
new AsyncSocketListener().StartListening(InitializeEndPoint());
}
public class AsyncSocketListener : IDisposable
{
public void StartListening(IPEndPoint endPoint)
{
try
{
var socket = new Socket(endPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(endPoint);
socket.Listen(10);
while (true)
{
string info = string.Format("{0} Waiting for a connection...", DateTime.Now.ToString("HH:mm.ss"));
Controller.StatusSignal.Reset();
Console.WriteLine(info);
Debug.WriteLine(info);
socket.BeginAccept(new AsyncCallback(SocketListener.AcceptCallback), socket);
Controller.StatusSignal.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("Closing the listener...");
}
The thread is still present in the Threads Window and is in the expected state so I'm at a loss as to why it refuses to wake up on client connection.
Should that be possible? I read the socket msdn page and it appears to suggest it should be OK for a background thread.
(After too much hair-pulling and a process of elimination)
The code is fine, (Windows) Firewall had blocked the binary using the background thread (without notifying, despite its settings) but had allowed the non-threaded version thru, hence why I originally thought it was a code issue.
So, yes, the async pattern shown above is perfectly fine running on a background thread as shown, and of course its quite a nice way of using it as you are simply sleeping the bg thread and your main (eg. UI) thread can operate normally.
Related
I'm facing asynchronous methods for the first time and I cannot understand the advantages of the following code on a synchronous version:
private void SendCallback(IAsyncResult ar)
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
// Signal that all bytes have been sent.
SendCompleted.Set();
}
private AutoResetEvent SendCompleted = new AutoResetEvent(false);
public bool Send(byte[] byteData)
{
try
{
RfTcpClient.Client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(this.SendCallback), RfTcpClient.Client);
}
catch (Exception)
{
return false;
}
return SendCompleted.WaitOne(1000, true);
}
I simplified it a bit so don't care about trivial error !
The Send method starts sending the message and then waits till the operation is completed without wasting cpu time. A new thread executes SendCallback which writes on the communication channel and it actively wait for the operation to complete, then signal the thread of the Send method.
I cannot see any advantages on synchronous method.
My assumption is that client.EndSend costs cpu time till it is completed, so the synchronous method is only moved to another thread. Am I missing something ?
I'm having problems listening for connections within a TCPListener, basically I am running this on a different thread as so:
listenThread = new Thread(new ThreadStart(Listen));
void Listen(...)
{
while (true)
{
Socket socket = Listener.AcceptSocket();
Connection connection = new Connection(socket);
connection.onInit();
Thread.Sleep(100);
Listen();
}
}
I have no idea what to do next to solve this "Stackoverflow" Exception, I need to listen to connections on a different thread like the way I've coded it, any suggestions to fix it?
Listen() is calling itself which will eventually result in a stack overflow.
Simply remove the call to Listen() at end of the while loop.
AcceptTcpClient() prevents app from exit after I called thrd.Abort().
How to exit application when in listening?
You should be able to interrupt the call to AcceptTcpClient() by closing the TcpListener (this will result in an exception being thrown by the blocking AcceptTcpClient(). You should not be aborting the thread, which is generally a very bad idea in all but a few very specific circumstances.
Here's a brief example:
class Program
{
static void Main(string[] args)
{
var listener = new TcpListener(IPAddress.Any, 12343);
var thread = new Thread(() => AsyncAccept(listener));
thread.Start();
Console.WriteLine("Press enter to stop...");
Console.ReadLine();
Console.WriteLine("Stopping listener...");
listener.Stop();
thread.Join();
}
private static void AsyncAccept(TcpListener listener)
{
listener.Start();
Console.WriteLine("Started listener");
try
{
while (true)
{
using (var client = listener.AcceptTcpClient())
{
Console.WriteLine("Accepted client: {0}", client.Client.RemoteEndPoint);
}
}
}
catch(Exception e)
{
Console.WriteLine(e);
}
Console.WriteLine("Listener done");
}
}
The code above starts a listener on a separate thread, pressing Enter on the console window will stop the listener, wait for the listener thread to complete, then the application will exit normally, no thread aborts required!
You could:
Use BeginAcceptTcpClient() and End.. instead:
See:https://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.beginaccepttcpclient(v=vs.110).aspx
Or your could:
Create a TcpClient and send your listener message:
therefore (I guess you have a loop in your thread):
break the loop wherein the listener.AcceptTcpClient() is running.
(i.e. CancelAsync()) from outside and
Loop While (!Tread.CancellationPending);
Create a TcpClient and send your listener a message (and discard data);
TcpClient see: https://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient(v=vs.110).aspx
Now your thread can go on with:
client.close() and listener.stop()
I have the following code, I want to abort a thread if it is unfinished in 2 secs.
You can see from the first code that i create a new myThread evertyime in the while loop and do not abort it. Well, I dont want to it to be like this, but if i take the myThread outside the loop and use the abort() function as the second code does. there will be error in aborting.
while (true)
{
try
{
m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//reset up socket
myThread = new System.Threading.Thread(new System.Threading.ThreadStart(socket_connect));
myThread.Start();
if (!myThread.Join(2000))
{
throw new SocketException(SocketError.AccessDenied);
}
}
catch (Exception ex)
{
m_socket.Close();
}
}
}
private static void socket_connect()
{
m_socket.Connect(remoteEndPoint);//Connect to remote device
}
I was trying the following code at first, however it give threadabortexceptions.
myThread = new System.Threading.Thread(new System.Threading.ThreadStart(socket_connect));
while (true)
{ try
{
m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//reset up socket
myThread.Start();
if (!myThread.Join(2000))
{
myThread.Abort();
throw new SocketException(SocketError.AccessDenied);
}
}
catch (Exception ex)
{
m_socket.Close();
}
}
}
private static void socket_connect()
{
m_socket.Connect(remoteEndPoint);//Connect to remote device
}
I know abort() is not a good idea so I turn to let the threads stay and let C#(.Net? I dont know who actually does that) dealing with the garbage collection. And can anyone tell if it is a good idea since this program will be run on a board which does not have lots of memory for holding bunches of threads. And can someone tell me how exactly the garbage collection is done in C#? for example the threads.
Another thing need to be mention is that i dont have the Task class, or the socket.beginconnect() method, I guess its because i'm building a program that is going to run on a small board, not a pc. The board is a netduido plus and I'm building my project on a netduino plus platform.
I have the following code, I want to abort a thread if it is unfinished in 2 secs.
Reading into the code, it looks like you actually want to attempt to connect a socket to a resource within two seconds. If more than two seconds elapses, you want to move on.
I'm mostly reproducing the code in this answer, I believe this is approximately what you should be doing to achieve your goal, rather than spinning up a thread and aborting it:
Socket socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
// Connect using a timeout (2 seconds)
IAsyncResult result = socket.BeginConnect( sIP, iPort, null, null );
bool success = result.AsyncWaitHandle.WaitOne( 2000, true );
if ( !success )
{
// NOTE, MUST CLOSE THE SOCKET
socket.Close();
throw new ApplicationException("Failed to connect server.");
}
// Success
//...
[edit: massive copypasta fail when untabbing/spacing]
Oh, please use the Task library, it's way easier to deal with these situations:
(LINQPad-friendly blob)
void Main()
{
var canceller = new CancellationTokenSource();
var task = Task.Factory.StartNew(() => DoStuff(canceller.Token), canceller.Token);
if(!task.Wait(2000, canceller.Token))
{
canceller.Cancel();
task.Wait(2);
}
sw.Elapsed.Dump();
}
private Stopwatch sw;
private void DoStuff(CancellationToken token)
{
try
{
sw = Stopwatch.StartNew();
while(!token.IsCancellationRequested)
{
}
}
// no catch - rethrown exceptions must be checked on Task
finally
{
sw.Stop();
}
}
Alternatively, you can use some "exit flag" condition - a bool that both your thread-starter and your thread-runner can see/alter, and use that in your while condition.
As title implies.
Yes, i know it's horribad to use .abort() but hear me out
I'm using 2 threads, The main thread (of my app) and a socket listen thread (familiar sound anyone?)
Instead of using asynchronous .AcceptAsync() calls (tbh, main reason is that i haven't looked too much into them), I have the thread just hang on socket.Accept();
Ofcourse, when i call thread.Abort(), the thread doesn't close because it's still waiting for a connection, once it passes Accept() it'll abort just fine.
Code:
void listenserver()
{
while (run)
{
fConsole.WriteLine("Waiting for connections..");
connectedsock = mainsock.Accept();
connected = true;
fConsole.WriteLine("Got connection from: " + connectedsock.RemoteEndPoint);
...
and elsewhere:
private void button_start_Click(object sender, EventArgs e)
{
if (!run)
{ //code ommitted.
}
else
{
run = false;
listenthread.Join(3000);
if (listenthread.IsAlive)
{
fConsole.WriteLine("Force-closing rogue listen thread");
listenthread.Abort();
}
button_start.Text = "Start";
groupBox_settings.Enabled = true;
}
is there any way of assuring the thread will end, not being to stuff the whole thing in a seperate app and then ending that?
Note that i DO have thread.IsBackground set to true (as suggested in other forum threads), it doesn't make any difference though.
Since you're already using a thread, you might as well just use BeginAccept. Async code doesn't need to complicate your code, since you can use lambdas like this:
var socket = new Socket(...);
socket.BeginAccept(result =>
{
if (this.abort)
{
// We should probably use a signal, but either way, this is where we abort.
return;
}
socket.EndAccept(result);
// Do your sockety stuff
}, null);
Even with a separate method definition for the AsyncCallback, the code isn't complex.
By doing async IO you're also being a lot more efficient with the CPU time, since between the call to BeginAccept and EndAccept, the thread can be reused for other processing. Since you're not using it for anything purposeful while waiting for the connection, holding up a thread is pretty meaningless and inefficient.