I know there are plenty of things about foreach freezing forms but I can't find a solution to my problem. I already have the server portion of this program working I am trying to make a client side that while connecting to the server this code will be preformed txtConn.AppendText("Attempting connection.");
This is the code that I have for the socket connection
private static Socket ConnectSocket(string server, int port, RichTextBox txtConn, BackgroundWorker backgroundWorker1)
{
Socket s = null;
IPHostEntry hostEntry = null;
// Get host related information.
hostEntry = Dns.GetHostEntry(server);
// Loop through the AddressList to obtain the supported AddressFamily. This is to avoid
// an exception that occurs when the host IP Address is not compatible with the address family
// (typical in the IPv6 case).
backgroundWorker1.RunWorkerAsync();
foreach (IPAddress address in hostEntry.AddressList)
{
IPEndPoint ipe = new IPEndPoint(address, port);
Socket tempSocket =
new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
Console.WriteLine(ipe);
try
{
attempt++;
txtConn.Select(txtConn.TextLength, 0);
txtConn.SelectionColor = Color.Aqua;
if (attempt == 1)
{
txtConn.AppendText("Attempting connection.");
}
else if (attempt > 1)
{
txtConn.AppendText("\r" + "Attempting connection.");
}
txtConn.SelectionColor = txtConn.ForeColor;
tempSocket.Connect(ipe);
}
catch (ArgumentNullException ane)
{
Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
txtConn.Select(txtConn.TextLength, 0);
txtConn.SelectionColor = Color.Red;
txtConn.AppendText("\r\n" + "Connection could not be established.");
txtConn.SelectionColor = txtConn.ForeColor;
}
catch (SocketException se)
{
Console.WriteLine("SocketException : {0}", se.ToString());
txtConn.Select(txtConn.TextLength, 0);
txtConn.SelectionColor = Color.Red;
txtConn.AppendText("\r\n" + "Connection could not be established.");
txtConn.SelectionColor = txtConn.ForeColor;
}
catch (Exception e)
{
Console.WriteLine("Unexpected exception : {0}", e.ToString());
txtConn.Select(txtConn.TextLength, 0);
txtConn.SelectionColor = Color.Red;
txtConn.AppendText("\r\n" + "Connection could not be established.");
txtConn.SelectionColor = txtConn.ForeColor;
}
if (tempSocket.Connected)
{
Console.WriteLine("Connected");
s = tempSocket;
break;
}
else
{
continue;
}
}
return s;
}
My program looks like this
When I run the program and connect with say the wrong Port, it checks all the possible ips on my computer and waits till after the foreach statement to display errors or anything. How can I make it actively display this?This is when it runs
You need to run your code in a different thread so that the UI can still update while it is executing.
The easiest way to do this is by adding the connection loop to a new task in the ThreadPool.
ThreadPool.QueueUserWorkItem(i => {
// Connection loop goes here.
});
If you need other options you can also use a Task, BackgroundWorker, etc.
I just answered a similar question here, but to expand on it for your particular case, it looks like you aren't actually using backgroundWorker1. The foreach should be done in a method referenced by the backgroundWorker1.DoWork event. You'll also need to create a method for the backgroundWorker1.ProgressChanged event. You can use ReportProgress to pass a string and then append that message to your textbox:
From your foreach loop in the Worker_DoWork method, you will report progress instead of updating the RichTextBox directly:
worker.ReportProgress(0, "Connection could not be established.");
And then in the Worker_ProgressChanged method, you will use something like this to update the RichTextBox:
txtConn.AppendText(e.UserState.ToString());
Use should use Async methods from Socket class or run this stuff in another thread. You can use BackgroundWorker to do that as well.
Related
I'm trying to make a game using sockets and UDP, i made a server class where when i call the start method i run a task with a loop to receive packets and process them, i used Socket.ReceiveFrom(packet, ref sender); inside a try catch block with everything inside a while loop, first i forgot to add Socket.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 25000)); so i got a loop of bind exeptions which is normal but now that i added this line my program is freaking out see the code bellow
public class UDPServer
{
public UDPServer()
{
Socket = new Socket(AddressFamily.InterNetwork ,SocketType.Dgram,ProtocolType.Udp);
Socket.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 25000));
}
public void Start()
{
IsBound = true;
try
{
Task.Run(NetworkLoop);
}
catch (Exception e)
{
throw e;
}
}
private void NetworkLoop()
{
EndPoint sender = new IPEndPoint(IPAddress.Any, 0);
byte[] packet = new byte[1];
int dataSize = 0;
while (IsBound)
{
try
{
dataSize = Socket.ReceiveFrom(packet, ref sender);
Console.WriteLine(sender.ToString() + " with " + packet.Length + " of " + dataSize);
}
catch (Exception e)
{
Console.WriteLine("Reading exeption : " + e.Message);
}
}
}
}
I debugged this and it seems that now when going step by step to the line
dataSize = Socket.ReceiveFrom(packet, ref sender); it just both exit the try catch block without any exeption catched AND breaks the while loop...
Is this normal behaviour ??
Your UDPServer.Start() method is not blocking, because Task.Run will run asynchronously.
Task.Run(NetworkLoop); // This is non-blocking
Your UDP server will work by either:
Task.Run(NetworkLoop).Wait(); // This is blocking
or
new UDPServer().Start();
Console.WriteLine("Press <enter> key to stop UDP server...");
Console.ReadLine(); // This block until user hit <enter> key
My target was to create a synchronized workspace for two clients (A GUI program that runs at both of them and synchronizing with text messages).
I have two buttons currently, the first one creates the socket with the server and the second one opens a new form (Form2 which is currently an empty form).
Clicking on button 2 will open the form for the current client and will send a message for the other client to open the form.
For some reason, the first form which is shown by clicking the button succeeds whereas the other client which is trying to be shown by the message from the first client does not succeed and is "not responding".
Why the form from the second client is not responding?
In both of the clients an instance of Form2 is defined before.
The code in both of the clients is the same code.
Code Samples:
1- Connect to the server by clicking button 1:
private void button1_Click(object sender, EventArgs e)
{
try
{
IPAddress ipAddress = new IPAddress(new byte[] { 127, 0, 0, 1 });
IPEndPoint remoteEP = new IPEndPoint(ipAddress, 11000);
Socket Server_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
Server_Socket.Connect(remoteEP);
Thread SendingThread = new Thread(new ParameterizedThreadStart(CrazySendingThread));
Thread RecievingThread = new Thread(new ParameterizedThreadStart(CrazyReceivingThread));
SendingThread.Start(Server_Socket); /*A thread that always sends the messages in 'msgtosend' list.*/
RecievingThread.Start(Server_Socket);/* A thread that always try to receive a message from the server(if there isn't it waits).*/
}
catch (ArgumentNullException ane)
{
Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
}
catch (SocketException se)
{
Console.WriteLine("SocketException : {0}", se.ToString());
}
catch (Exception ex)
{
Console.WriteLine("Unexpected exception : {0}", ex.ToString());
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
2- Open a new form by clicking button 2:
private void button2_Click(object sender, EventArgs e)
{msgtosend.Add(Encoding.ASCII.GetBytes("/OpenNP"));
Np.Show();/* Np is defined as a global variable and built in Form1_load*/}
3- CrazyReceivingThread - the thread that always tries to receive:
public void CrazyReceivingThread(object srv)
{
string msg = "";
Socket srvr = (Socket)srv;
byte[] data = new byte[1024];
while (true)
{
System.Threading.Thread.Sleep(20);
int bytesRec = srvr.Receive(data);
msg = Encoding.ASCII.GetString(data, 0, bytesRec);
string[] msg_array = msg.Split(' ');
try {
switch (msg_array[0])
{
case "/Mouse_pos":
{/*is not relevant for the question...*/}break;
case "/OpenNP":
{
try
{
Np.Show();
}
catch /*The form is 'Not responding' but this exception is **not** being caught.*/
{
Console.WriteLine("Form is not shown.");
}
}
break;
}
} catch(ArgumentNullException e) {
Console.WriteLine(e.Message);
}
}
}
The reason that your form is not responding is that you are trying to launch a Form in a background thread. You will need to open the form from the UI thread (the thread that contains the message pump). This is done by calling Invoke (or BeginInvoke). Since you don't list the main form code, I can't tell you an exact code replacement, but what you want to do is pass a reference to the main form into your thread method and in that method you want to invoke the Form.Show call:
case "/OpenNP":
{
try
{
// where mainForm is a reference to the form
// that contains the buttons, the main form that is shown
mainForm.Invoke((Action)(() => Np.Show()));
}
catch (Exception ex)
{
Console.WriteLine("Form is not shown. " + ex.ToString());
}
}
break;
I'm studying network and Windows forms with C# these days.
I'm trying to build an async-socket network system, everything's working well.
codes for Connect and Connect Callback are below.
private void ClientConnect()
{
CheckForIllegalCrossThreadCalls = false;
try
{
socket.BeginConnect(endPoint, new AsyncCallback(ConnectCallback), socket);
connectDone.WaitOne();
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
Send(socket, textBox3.Text, 0);
connectDone.Set();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
But in disconnecting socket, there's a problem.
I make a button to disconnect socket, and codes for button-clicked event are below.
private void btnDisconnect_Click(object sender, EventArgs e)
{
try
{
socket.Shutdown(SocketShutdown.Both);
Application.DoEvents();
socket.Disconnect(true); //-> problem occurs.
}
catch
{
MessageBox.Show("Disconnect Error!");
}
if (socket.Connected)
MessageBox.Show("Disconnect Error!");
else
textBox1.AppendText("Disconnected! (" + DateTime.Now.ToString("h:mm:ss tt") + ")\n");
}
When I disconnect the socket, 2 minutes of waiting time occurs.
after 2 minute(I checked this with time-stamp), It shows 'Disconnected' message.
And I can re-connect with this socket.
I think it is not just waiting like sleep, something's processed in background.
(Because mouse cursor's changed and program's blocked)
I'm so wondering why this delay(?) happens.
Please let me know.
I have a fairly weird question? I have seen on web how to pass control from main class to another class, and this is said to work, but it does not?
What I am trying to do is create a simple asynchronous TCP client-server connection, which would send messsage from client to server. Problem is when I want to update client's textblock, application exits (no error just closes). I only have one main thread so I don't think I need to have an Invoke.
Code from main class:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void connect_ClickEvent(object sender, RoutedEventArgs e)
{
try
{
_statusPanel.Text += "Sending request to server (IP address: " + _ipTextBox.Text + ", port number: " + _portTextBox.Text + ")\n";
_statusPanel.Text += "Connecting.....\n";
AsynchronousClient.setStatusPanel(_statusPanel);
AsynchronousClient.setPort(Convert.ToInt32(_portTextBox.Text));
AsynchronousClient.setIpAddress(_ipTextBox.Text);
AsynchronousClient.StartClient(_message.Text);
_statusPanel.Text += "... connection established!\n";
_statusPanel.Text += "Enter the string to be transmitted !\n";
}
catch (Exception ee)
{
_statusPanel.Text += ee.StackTrace + "\n";
}
}
}
Code from another class:
public class AsynchronousClient
{
// The port number for the remote device.
private static int port;
private static IPAddress ipAd;
public static TextBlock statusPanel;
public static void setStatusPanel(TextBlock status)
{
statusPanel = status; //That's my setter for statusPanel which I want to update
}
public static void StartClient(string message)
{
// Connect to a remote device.
try
{
IPAddress ipAddress = ipAd;
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
string sendingMessage = message + "<EOF>";
Send(client, sendingMessage);
sendDone.WaitOne();
Receive(client);
receiveDone.WaitOne();
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch (Exception e)
{
statusPanel.Text += e.ToString() + "\n";
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
//This next line is where my program closes without error
statusPanel.Text = "Socket connected to " + client.RemoteEndPoint.ToString() + "\n";
connectDone.Set();
}
catch (Exception e)
{
statusPanel.Text += e.ToString() + "\n";
}
}
**If I replace "statusPanel.text" with "Console.WriteLine" everything works just fine! Anybody knows what I am doing wrong? **
AsyncCallback will be called on separate thread and not on main thread so you can't update textBox value from other thread. You can only do that from main UI thread.
So, you have to delegate it on main thread like this:
statusPanel.Dispatcher.Invoke(new Action(() =>
statusPanel.Text = "Socket connected to " +
client.RemoteEndPoint.ToString() + "\n"));
You method ConnectCallback will not be executed on the WPF User Interface thread, but instead will be invoked by the socket class on a background thread of the thread pool. In this method, you set the Text of the StatusPanel.
Use StatusOanel.Dispatcher.Invoke to execute your method on the UI Thread. If you want to learn more about it, this article might be a thing: http://msdn.microsoft.com/en-us/magazine/gg598924.aspx
When I want to open a new Thread for every Incoming Request. Is this good way to do it? Will there be a new Thread with every accepted Request? The BeginReceive Method called in the end of this piece of code Works asynchronous aswell.
public void Listen(IPEndPoint EndPoint)
{
try
{
ListeningSocket.Bind(EndPoint);
ListeningSocket.Listen(BACKLOG);
BeginAccept();
}
catch (Exception e)
{
Console.WriteLine(e.Message + "\nfrom Source: " + e.Source + "\nand Stack Trace: " + e.StackTrace);
}
}
public void BeginAccept()
{
try
{
ListeningSocket.BeginAccept(new AsyncCallback(Accept_Callback), new ServerSocket());
}
catch (SocketException e)
{
Console.WriteLine("Listening Socket Error:" + e.ErrorCode);
}
catch (ObjectDisposedException e)
{
Console.WriteLine("The Listening Socket has been closed");
}
}
private void Accept_Callback(IAsyncResult asyncResult)
{
BeginAccept();
try
{
if (asyncResult.AsyncState != null)
{
ServerSocket serverSocket = asyncResult.AsyncState as ServerSocket;
if ((serverSocket.CommunicationSocket = ListeningSocket.EndAccept(asyncResult)) != null)
{
BeginReceive(serverSocket);
}
}
}
catch (SocketException e)
{
Console.WriteLine("Listening Socket Error:" + e.ErrorCode);
}
catch (ObjectDisposedException e)
{
Console.WriteLine("The Listening Socket has been closed");
}
}
This approach uses threads from a ThreadPool which is a good thing. While waiting for a new client to be accepted or for data to arrive no threads are used, so your code will not span 1000 threads when you have 1000 clients connected.
Just when data arrives on one socket, one free thread will be taken from the tread pool and will process your callback. When your method finishes, the thread will be returned to the pool to be available for the next data arrival or client connection.